Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Symfonia C++ - Rozwiązania Ćwiczeń


Rekomendowane odpowiedzi

Opublikowano

Witam, po tej stronie Approx ;) Dzisiaj postanowiłem zabrać się za Symfonie C++ Jerzego Grębosza, od początku bo zawsze się gdzieś zatrzymywałem i książke odkładałem na bok. Po przeczytaniu pierwszego rozdziału, przyszło mi do głowy aby zrobić odpowiedzi do każdego rozdziału, aby rozwiać wątpliwości takich "ogórków" jak ja ;) Odpowiedzi, które są udzielane tutaj, są wywnioskowane z książki oraz niekiedy wujka google, będę się starał w miare możliwości dodawać(co około 3 dni), jeden rozdział + rozwiązania dla niego. Myślę, że to się przyda i może w przyszłości zasłuży na podpięcie.Liczę na krytykę oraz miłej lektury;>

1. Ćwiczenia – Startujemy

 

 

I. Które z poniższych nazw są poprawne, a które niepoprawne i dlaczego?

 

 

a) predkosc4

(b Predkosc_i_czas
c) 4kola // niedopuszczone - zmienna nie może zaczynać się od cyfry.

d) wielki.czwartek // ze znaków specjalnych dozwolony jest tylko _

e) ilosc_powtorzen_cyklu_roboczego

f) _zmienna(dopuszczalny, ale nie zaleca się stosowania)

g) samochod-osobowy // ze znaków specjalnych dozwolony jest tylko _

j) auto // dział nazw zakazanych

k) kwota_zainwestowanych_$ // ze znaków specjalnych dozwolony jest tylko _

i) wspolczynnik_(chwilowego)_przyrostu // ze znaków specjalnych dozwolony jest tylko _

m) export_pszenicy

n) export // dział nazw zakazanych

 

 

 


II. Wymień zasadnicze etapy niezbędne do stworzenia i uruchomienia programu.

 

 

a) Edycja

(b Kompilacja

c) Linkowanie

 

 

 


III. Czy jedna instrukcja może być zapisana w trzech liniach?

 

 

Tak, ale średnik musi być na końcu instrukcji, jeśli będzie
inaczej, kompilator to potraktuje jako oddzielne instrukcje.

 

 

 

 

IV. Czy w jednej linii programu można umieścić kilka instrukcji?

 

 

Tak, ale instrukcje muszą być oddzielone średnikami.

 

 

 

 

V. Jak rozpoznaje się koniec instrukcji?

 

 

Średnikiem na końcu.

 

 

 


VI. Czy definicja jest równocześnie deklaracją – a może odwrotnie?

 

 

Definicja jest równocześnie deklaracją.

 

 

 


VII. Co to są tak zwane „białe znaki”? Wymień trzy, z którymi do tej pory się spotkaliśmy.

 

 

Białe znaki, są to:

a)Enter

(bSpacja

c)Tabulacja

Kompilator je ignoruje, pomagają programiście zachować „jasność”
kodu oraz ułatwić późniejszą modyfikację.

 

 

 


VIII. Powiedzieliśmy, że w programie każda nazwa, przed jej uzyciem, musi zostać zdeklarowana. W naszych dotychczasowych programach
wystapiła nazwa cout. Gdzie była jej deklaracja?

 

 

Deklaracja cout

była na samym początku programu, podczas linkowania w bibliotece <iostream> - podstawowej biblioteki C++.

 

 

 

 

IX. Zastanów się, które ze znanych Ci edytorów mogą posłużyć
do napisania programu w C++

a) Code::Blocks

(b Microsoft Visual C++

c) Notatnik(tylko do pisania kodu źródłowego)

 

 

X. Do czego służy kompilator C++?

 

 

Kompilator służy do przekładu kodu źródłowego(C++), na kod
maszynowy(procesora).

 

 


XI. Do czego służy linker?

 

 

Do przyłączania bibliotek do naszego programu, bądź plików
stworzonych przez innego programistę, których potrzebujemy.

 

 

 


XII. Czy w komputerze, z którym masz do czynienia – istnieją jakieś kompilatory C++?

 

 

(Tutaj odpowiedz sobie sam)

 

 

 

 

XIII. Napisz program, który z pomocą jednej instrukcji cout napisze na ekranie nastepujący tekst:

 


W i t a m y
na
p
o
kladzie


#include <iostream>

int main()
{

std::cout << "w i t a m y \n" << "na \n" << "p \n" << "o \n"<< "kladzie\n";

}

 

 


XIV. Napisz program pozwalający przeliczyć cale na centymetry( 1 cal = 2.54 centymetra).

 


#include <iostream>
int main()
{
double cale;
double centymetry;
double przelicznik = 2.54;

std::cout << "Podaj liczbe cali: \n";
std::cin >> cale;
metry = cale * przelicznik;

std::cout << "\n";
std::cout << cale << " cali, to jest: " << centymetry << " centymetrow.\n";
}

 

 

 

 

XV. Co określa deklaracja danej nazwy?

 

 

Deklaracja mówi jakiego typu jest to, co nazywamy daną nazwą

 

 

 

 

XVI. Jakie znasz sposoby umieszczania w tekście programu komentarzy?

 


a) Jednoliniowe:
// tu jakiś tekst
B)Wieloliniowe:
/*
tu jakiś tekst
Tu też…
tekst
// dalszy tekst..
Koniec komentarza */

 

 


XVII. Czy
poprawne są poniższe komentarze? Jeśli nie to dlaczego?

 


a)

/*
to jest pierwszy
komentarz // drugi
// trzeci
// czwarty
A to dokończenie
***************/

Dobrze, wolno zagnieżdżać komentarze „//” w „ /* …*/ ”.

(b

// wysokość = 660; // proba nieudana
Dobrze, kompilator ignoruje wszystkie znaki w linii po „//”.

c)
/*---------
szerokosc= 23; // wstepna wartosc
gestosc = 12.55; /* wzieta z tablic */
// dalsze obliczenia
---------------*/
Ten jest źle, ponieważ nie wolno zagnieżdżać
komentarzy typu /* .. */.

 

 


XVIII. Jeśli wiesz już, jakim edytorem(lub środowiskiem) będziesz się posługiwał –

sprawdź czy ma on udogodnienia związane ze stawianiem komentarzy typu // w
wielu liniach równocześnie.

 

 

W moim przypadku: Code::Blocks, ma takie udogodnienie: Shift + Ctrl + C.

 

 

 

 


2. Instrukcje sterujące – Ćwiczenia


I. Czym sterują poznane w tym rozdziale instrukcje sterujące?


Kolejnością działania programu.


II. Mamy wyrażenie logiczne (y < 0 , jakie mogą być jego
wartości?


True albo False


III. Czy w miejscu gdzie program spodziewa się wyrażenia
logicznego, można postawić na przykład obiekt(zmienną) typu całkowitego int?
Jak zareaguje program napotykając obiekt zamiast warunku?


Można, program będzie reagował tak:
jeśli zmienna będzie różna
od 0, będzie wskazywał na prawdę, a jeśli będzie równa 0, będzie mówił, że jest to fałsz.




IV. Załóżmy, że mamy obiekt typu int o nazwie a. Które z
następujących konstrukcji if są dopuszczalne?




int a;
// … nadanie wartości obiektowi a
a) if(a < 6) jakaś instrukcja;
(b if(a) jakaś instrukcja;
c) if(a+2) jakaś_instrukcja;
d) if( (a + 7)< (10 -2) ) jakaś instrukcja;
e) if((a+a)> (a – 4) ) jakaś_instrukcja;


V. W poniższym pseudo-kodzie trzykrotnie wystepuje słowo
kluczowe else. Do którego if należą tak umieszczone słowa else? Odpowiedz
podając naze warunku przy danym if.






if(warunek1)
{
If(warunek2) jakaś instrukcja;
If(warunek3) jakaś instrukcja;
else jakaś_instrukcja; // else nr. 1
}
else // else nr. 2
if(warunek4)
if(warunek5) jakaś_instrukcja;
else // else nr 3
jakaś instrukcja;


Else nr.1 należy do warunku3, else nr.2 należy do warunku1, a else nr.3 należy do
warunku5.


VI. Na czym
polega pętla programowa?


Na działaniu programu,
dopóki nie zostanie spełniony jakiś warunek.


VII. Które z trzech poznanych petli programowych mogą sprawić, że zawarte w nich
instrukcje(instrukcje będące ich treścią) nie będą wcale wykonane?


Pętla for, while


VIII. Jaka
jest zasadnicza różnica między pętlą programową zrealizowaną za pomocą:


a) instrukcji while;
(b instrukcji do-while;
Co z tej różnicy wynika?

Instrukcja while, najpierw sprawdza warunek i jeśli nie jest spełniony nie
wykona się ani razu, a pętla do while sprawdza warunek na końcu i wykona się co
najmniej raz, nawet jeśli warunek jest niespełniony.



IX. Kiedy w instrukcji for sprawdzany jest warunek – przed,
czy po obiegu pętli?


Przed obiegiem pętli.


X. Wewnątrz
nawiasu instrukcji for są dwa średniki. Po drugim z nich jest instrukcja, którą
roboczo nazwaliśmy instrukcją kroku pętli. Kiedy jest ona wykonywana -
przed czy po obiegu pętli?


Po obiegu pętli.


XI. Podaj przykłady realizacji nieskończonej pętli za pomocą trzech poznanych rodzajów
pętli(for, while, do while)


a) while(true) jakas_instrukcja;
(b for( ; ; ) jakas_instrukcja;
c) do jakas_instrukcja while(true);


XII. Pętla jest nazywana „nieskończoną”, gdy jej warunek
jest zawsze prawdziwy, więc nie
ma szansy, by przerwał on pracę tej pętli. Za pomocą jakich instrukcji można(z
pozycji programu) zakończyć pracę pętli i spowodować przejście do wykonywania
instrukcji po niej bezpośrednio następujących? Podaj dwa sposoby.


a) Za pomocą instrukcji break;
(b Za pomocą goto;


XIII. Jak można zakończyć prace nieskończonej pętli i przejść do o wiele dalszych
instrukcji, a nawet takich poprzedzających ją?(Czyli jakby „wrócić”)?


Za pomocą
instrukcji goto;


XIV. Jaka
jest różnica między obiektem zdefiniowanym w wyrażeniu inicjalizacyjnym pętli

for, a takim samym obiektem zdefiniowanym o jedną linijkę
powyżej tej pętli for?


Obiekt zdefiniowany w środku, ma tylko zakres lokalny wewnątrz pętli, poza już nie
można go wywołać, ani nic z nim
zrobić.


XV. Czy poprawna jest taka instrukcja switch?



int m;
// … nadanie wartości obiektowi m
switch(m)
{
case 1:
// …
break;

default:
// ...
break;

case 5-2:
// …
break;

case 5-4:
//…
}



Nie jest poprawna, gdyż case 1 oraz
case 5-4 się pokrywają.



XVI. Jakie konsekwencje ma nie umieszczenie instrukcji break po instrukcjach danej
etykiety case?


Nieumieszczenie break, będzie
powodowało wykonywanie kolejnych case’ów, pod casem,
który wywołaliśmy oraz dalszej części programu




XVII. Wyboru wielowariantowego można dokonać przy użyciu instrukcji switch lub if…else.
Przypomnij trzy aspekty, w których obie te instrukcje się różnią.


a) Przy instrukcji switch, musi być zmienna całkowita(int), lub wyrażenie typu
całkowitego, przy
if…else, nie ma to różnicy


(b Zmienna
wybierająca, musi być porównywana do stałej w instrukcji switch, a w instrukcji if…else może
być porównywana do zmiennej.



c) Switch – porównanie
do liczby x, if…else porównywanie
może być zmienne.


XVIII. Mamy dokonać wyboru wariantu działania programu
zależnie od ilości próbek
przebadanych przez układ pomiarowy. Jeśli jest ich 6, to podejmujemy działania,
jeśli jest ich 12, to działania, a w każdym innym przypadku działaniaC. Czy
można się w tym celu posłużyć instrukcją sterującą switch?


Można.


XIX.
Zadanie podobne do poprzedniego, lecz nieco zmienione. Mamy dokonać wyboru
wariantu działania programu zależnie od ilości próbek przebadanych przez układ
pomiarowy. Jeśli jest ich 6, to podejmujemy działania, jeśli jest ich 12 to
działania B, a jeśli więcej niż 12, to działaniaC. Czy można się w tym celu
posłużyć instrukcją switch?


Nie można.


XX. Mamy dokonać wyboru wariantu działania programu zależnie od wielkości przychodu
wyrażonego w złotych(bez groszy). Są trzy progi podatkowe(stałe). Zależnie od
wielkości dochodu(między którymi jest progami) podatek oblicza jedna z czterech
procedur. Czy można się tu posłużyć instrukcją switch do wybrania odpowiedniej
procedury?


Nie, dlatego, że są to zmienne.


XXI. Jakie
działanie może mieć instrukcja break umieszczona w pętlach for, while,
do-while? Jak działa w przypadku, gdy te pętle są zagnieżdżone?


"Przełamuje”
tylko jedną pętle.


XXII. Jaką
instrukcją sterującą możemy posłużyć się, by wydostać się z wielokrotnie
zagnieżdżonych pętli?


Instrukcją goto;


XIII. Co to
jest etykieta?


Nazwa zakończona dwukropkiem.


XXIV. Jakie
działanie w pętlach ma instrukcja continue?


Przechodzi od razu do kolejnego obiegu pętli.



XXV. Jeśli
w trakcie wykonywania treści pętli for napotkana zostanie instrukcja continue,
to co najpierw zostanie wykonane – sprawdzenie warunku, czy instrukcja krokowa?


Instrukcja krokowa.



 

3. Typy - Ćwiczenia

 


I. Deklaracja jest wyjaśnieniem czegoś kompilatorowi na temat naszego programu. Jeśli deklarujemy nazwę nnn, to wyjaśniamy, że co?

Wyjaśniamy, że nazwa nnn, jest jakiegoś typu



II. Wyjaśnij jaka jest różnica między definicją, a deklaracją. Czy są to pojęcia rozłączne, czy też jedno jest szczególnym rodzajem drugiego? Jeśli tak, to które jest rodzajem którego?

Deklaracja jest to wyjaśnienie, że dana nazwa jest jakiegoś typu, a definicja do tego rezerwuje miejsce w pamięci niej. Definicja jest równocześnie deklaracją.



III. Czy możliwe jest powtórzenie tej samej deklaracji w danym zakresie ważności?

Nie(nie zawsze).



IV. Czy możliwe jest powtórzenie tej samej definicji w danym zakresie ważności?

Nie.



V. Co powołuje do życia obiekt o nazwie nnn. Jego deklaracja, czy definicja?

Definicja



VI. Jaka jest relacja między typami złożonymi, a typami fundamentalnymi?

Typ złożony – składa się z typów fundamentalnych



VII. Wymień typy przeznaczone do pracy z liczbami całkowitymi. Podaj ich nazwy w wariantach „ze znakiem” i „bez znaku”.

signed int, unsigned int, signed short, unsigned short, signed long, unsigned long, char, long long



VIII. Jeśli przy deklaracji obiektu typu int nie zaznaczyliśmy czy chodzi o wersję „ze znakiem”, czy „bez znaku” – który wariant wybierze kompilator?

Wersję ze znakiem



IX. Co to są znaki alfanumeryczne?

Znaki alfabetyczne + numeryczne, pojedyncze litery, numery + znaki specjalne



X. Podaj nazwę typu mogącego przechowywać znaki alfanumeryczne z podstawowego zestawu(np. ASCII).

Char



XI. Jeśli w w powyższym typie nie zaznaczyliśmy czy chodzi o wersję „ze znakiem”, czy „bez znaku” – który wariant wybierze kompilator?

Zależnie od kompilatora



XII. Podaj nazwę typu przeznaczonego do przechowywania rozszerzonego zestawu znaków alfanumerycznych.

wchar_t



XIII. W języku C typ przeznaczone do przechowywania rozszerzonego zestawu znaków alfanumerycznych uzyskany jest dzięki typedef. Instrukcja ta( jak już wiemy) nie tworzy nowego typu, ale nadaje nową , dodatkową nazwę jakiemuś już istniejącemu). Czy w C++ typ ten jest odrębnym typem, czy może stworzonym przez typedef?

Odrębnym



XIV. Wymień trzy typy przeznaczone do pracy z liczbami zmiennoprzecinkowymi. Czy stosuję się do nich specyfikatory signed/unsigned?

float, double, long double – nie stosuje się.



XV. Wymień nazwę typu przeznaczonego do pracy ze zmiennymi logicznymi. Ile różnych wartości może przyjmować obiekt takiego typu? Jakie to wartości?

bool, dwie wartości – true, false



XVI. Jakie naprawdę wartości liczbowe reprezentują możliwe „stany” obiektu typu logicznego .

True – 1, False – 0


XVII. Czy do typu bool można zastosować specyfikator signed?

Nie



XVIII. Jeśli dany kompilator rezerwuje dla typu short int dwa bajty pamięci(czyli 16 bitów) to liczbę z jakiego przedziału można w nim zapisać? Podaj w przybliżeniu , w zaokrągleniu do tysięcy.

-32000 do 32000



XIX. Co zrobić, jeśli jakaś ujemna liczba nie mieści się w obiekcie typu short int? Jakim innym typem można wtedy się posłużyć?

Int, long int



XX. Gdzie definiować można obiekty w języku C++:


Jedynie powyżej instrukcji wykonywalnych,
Nawet wśród instrukcji wykonywalnych.



XXI. Jeśli mamy pętle for, w której instrukcji inicjalizującej jest definicja obiektu o nazwie „i”, to czy w instrukcji postawionej bezpośrednio po zakończeniu pętli możemy zdefiniować nowy obiekt o nazwie „i”?

Tak



XXII. W wyrażeniu warunkowym instrukcji if można definiować obiekt. Jaki zakres ważności ma ten obiekt?

W bloku if, oraz należącego do niego else



XXIII. Co to jest stała dosłowna? Czy obiekt stały mieszczący w sobie wartość 3.14 – to jest stała dosłowna?

Stałe dosłowne to tylko wartości. To nie jest stała dosłowna.



XXIV. Zapisz tę samą wartość np. 17 w postaci stałej dosłownej w zapisie dziesiątkowym, ósemkowym i szesnastkowym.


17 = 021 = 0x11



XXV. Zapisz wartość 10 w postaci stałej dosłownej typu: int, long, unsigned int, unsigned long, dobule, float.

10, 10L, 10u, 10uL, 10. = 1e1, 10.F



XXVI. Zapisz liczbę 15.6 w postaci stałej dosłownej typu double oraz float. Użyj najpierw zapisu dziesiętnego(zwykłego), a następnie wykładniczego.


double:15.6e1, 15.6
float: 15.6e1F, 15.6F



XXVII. Mogą być tylko dwie stałe dosłowne typu bool. Podaj je.

0, 1



XXVIII. Jakiego typu jest nastepująca stała znakowa ‘w’?

char



XXIX. Zapisz stałe dosłowne reprezentujące następujące znaki specjalne: tabulator, znak nowej lini, odwrotny ukośnik, sygnał dźwiękowy?


Tabulator – ‘\t’
Nowa linia – ‘\n’
Backslash – ‘\\’
Sygnał dźwiękowy – ‘\a’



XXX. Zapisz jako stałą dosłowną znak o kodzie 2f(szesnastkowo).

47



XXXI. Zapisz jako stałą dosłowną znak o kodzie 10(ósemkowo).

8



XXXII. Zapisz jako stałą dosłowną literę m, tak by owa stała była typu wchar_t.

L’m’



XXXIII. Zapisz w postaci stałej dosłownej typu C-string swoje imię i nazwisko. Następnie miedzy imię i nazwisko wstaw znak nowej linii.

”Imię \nNazwisko”



XXXIV. Co zrobic, jeśli stała dosłowna typu C-string jest tak długa, że nie możemy jej zmieścić w jednej linii tekstu programu. Czy można dokończyć jej pisanie w linii następnej? Jak to zrobić, by ostatecznie uzyskać i tak jeden długi C-string?

Nie można tego, dokończyć w linii następnej. Trzeba w jednej linii zamknąć cudzysłów i od drugiej linii znowu otworzyć i napisać resztę zdania, tak jak np. tutaj:
std::cout << „Bardzo długi długi długi długi długi długi długi długi długi długi długi długi”

 

„C-String”[/color]

 

XXXV. Jaka jest relacja między typami złożonymi, a typami fundamentalnymi?

Typ złożony jest zbudowany z typów fundamentalnych i operatora



XXXVI. Czy void to typ fundamentalny, czy złożony?

Fundamentalny



XXXVII. Czy można definiować obiekt typu void?

Nie, typ void tylko w deklaracji typu złożonego



XXXVIII. Co to jest czas życia obiektu?

”Okres od momentu, gdy zostaje on zdefiniowany, do momentu gdy przestaje istnieć”



XXXIX. Co to jest zakres ważności nazwy obiektu?

Zakres, w którym dany obiekt jest dostępny



XL. Jaka jest różnica między powyższymi dwoma pojęciami?

Obiekt może istnieć, ale nie być dostępny



XLI. W tzw. Bloku, czyli fragmencie programu ujętym w znaki klamry {}, definiujemy gdzieś obiekt o nazwie m. Jaki zakres ma ta nazwa, czyli od jakiego miejsca w programie ta nazwa jest znana i kiedy przestaje być znana. Czy do takiej nazwy można się do niej odnieść spoza tego bloku?

Taka nazwa jest znana tylko od momentu jest zdefiniowania do końca bloku. Przestaje być znana po skończeniu się bloku, oraz nie można się do niej odnieść.



XLII. To pytanie jest dla wtajemniczonych – wiedzących, co to jest funkcja, Czy za pomocą instrukcji Goto można przeskoczyć do wnętrza innej funkcji? Jaki zakres ma etykieta? Czyli o jakiego miejsca w programie ta nazwa jest znana i kiedy przestaje być znana?

Etykieta ma zakres ważności funkcji, znana w całej, niezależnie gdzie jest oraz nie jest znana poza funkcją



XLIII. Co to znaczy, że nazwa jest globalna. Jeśli na program składa się z kilka plików źródłowych, to czy nazwa globalna z jednego z nich jest znana w pozostałych?

Nazwa globalna jest znana w całym pliku i nie jest znana w innych plikach źródłowych.



XLIV. W danym programie po służyliśmy się dyrektywą
#include <iostream>
Co zrobić, by moc odnosić się do nazwy cout bez konieczności używania kwalifikatorów zakresu(std::cout). Podaj dwa sposoby.

Po linkowaniu bibliotek dodać dyrektywę: using std::cout



XLV. Na czym polega zasłonięcie nazwy globalnej przez nazwę lokalną?

Gdy istnieje nazwa globalna, możemy stworzyć taką samą lokalnie ale będzie „żyła” tylko w bloku.



XLVI. Jak z lokalnego bloku, w którym globalna nazwa została zasłonięta przez nazwe lokalną –odnieść się do zasłoniętej nazwy globalnej?

Poprzez operator::



XLVII. Jeśli mamy zagnieżdżone dwa bloki, a w tym głębiej zagnieżdżonym – lokalna nazwa załania inną lokalną – to jak możemy odnieść się do tej zasłoniętej nazwy lokalnej?

Nie możemy się do niej odnieść.



XLVIII. Jaka jest różnica między inicjalizacją, a przypisaniem?

Inicjalizacja to początkowe nadanie wartości, a przypisanie to późniejsze nadawanie wartości temu samemu obiektowi



XLIX. Czy można przypisać jakąś wartość do przed chwilą utworzonego obiektu z przydomkiem „const”?

Nie.



L. Co daje przydomek „register”?

Obiekt wtedy jest dodawany do rejestru, czyli miejsca szybkiego dostępu w programie(jest to zależne od kompilatora).



LI. Jaki jest cel stosowania przydomka „volatile” . O czym informuje on kompilator?

Informuje on kompilator, o tym, że obiekt może zmieniać swoją wartość bez jego wiedzy i ma na niego uważać.



LII. Do czego służy instrukcja typedef? Czy dzięki niej tworzymy nowy typ?

Tworzymy jedynie synonimy danego typu, ułatwiając sobie prace.



LIII. Czy instrukcja enum tworzy nowy typ, czy może jej rezultat jest wariantem innego fundamentalnego typu?

Tworzy osobny typ.



LIV. Jeśli na liście wyliczeniowej pierwszej nazwie nie przypiszemy żadnej wartości, to jaką wartość otrzyma ona przez domniemanie?

0



LV. Jeśli na liście wyliczeniowej jednej z kolejnych nazw nie przypiszemy żadnej wartości, to jaką wartość otrzyma ona przez domniemanie?

Liczbę o 1 większą poprzedniej



LVI. Czy typ wytworzony przez enum jest typem zmiennoprzecinkowym, czy może całkowitym?

Całkowity



LVII. Czy na liście wyliczeniowej możemy umieścić stałą dosłowną 3.14?

Nie



LVIII. Mamy dwa typy wyliczeniowe. Tak się składa, że w jednym nazwa xxx reprezentuje stałą wartość 89. Jeśli w drugim z nich jest nazwa yyy, która także reprezentuje wartość 89, to czy w kontekstach, gdzie program spodziewa się nazwy xxx, można posłużyć się nazwą yyy?

Nie

 


 

4. Operatory – Ćwiczenia

 


I. Co to znaczy, że operator jest dwuargumentowy lub jednoargumentowy. Wyjaśnij to na przykładzie dwóch operatorów: dwuargumentowego(minus) i jednoargumentowego(minus). Są to dwa różne operatory oznaczane tym samym symbolem.

Dwuargumentowy – działa na dwóch argumentach: 2 - 1
Jednoargumentowy – działa na jednym argumencie : -1


II. Posługując się operatorem „reszta z dzielenia” napisz program, który wypisywał będzie na ekranie kolejne liczby całkowite począwszy od 1 do 100, a po zakończeniu każdej 10stki wypisze „zakończona dziesiątka”




#include <iostream>
int main()
{
for(int i = 1; i<=100;++i)
{
std::cout << i << '\t';
if(!(i)) std::cout << "zakonczona dziesiatka!\n";
}
}


III. Używając operatora „reszta z dzielenia” – napisz program, który będzie wypisywał na ekranie kolejne litery alfabetu. Pierwszych osiem (A-H) ma być wypisywanych po dwie litery w jednym rzędzie, a co do następnych, to program ma zadać użytkownikowi pytanie(po ile liter w rzędzie ma wypisywać dalej). Zależnie od tej odpowiedzi następne litery mają być wypisywane wg. nowej zasady.



#include <iostream>
using namespace std;

int main()
{
short kolumny = 2, numerowanie = 1;

for( char litera = 'A'; litera <= 'Z'; litera++, numerowanie++)
{
cout << litera;
if( numerowanie % kolumny) cout << "\t";
else cout << "\n";

if( litera == 'H')
{
numerowanie = 0;
cout << "Po ile liter w rzedzie mam wypisywac? ";
cin >> kolumny;
if (kolumny==0) return 0;
}
}

cout << endl;
}


IV. Jak jest różnica między operatorem preinkrementacji(++x), a operatorem postinkrementacji(x++)?

Preinkrementacja, od razu podnosi wartość o 1, a preinkrementacja dopiero później(W niektórych przypadkach preinkrementacja jest szybsza niż postinkrementacja.


V. Jaka liczba pojawi się na ekranie na skutek działania następujących instrukcji
int a = 4;
cout << (a = 7) << endl;

7


VI. Jaka jest różnica między operatorami arytmetycznymi, a logicznymi – jeśli chodzi o typ rezultatu.

Operatory arytmetyczne dają rezultat w kształcie liczby, a logiczne true/false


VII. Omów różnicę między operatorem =, a operatorem ==

= - operator przypisania
== - operator porównania


VIII. Który z operatorów =, == może się znaleźć wyrażeniu warunkowym instrukcji if ? Czyli czy poprawne są konstrukcje:
A if(x = y)
B if(x == y)
Co zrobić by uniknąć tu ostrzeżeń kompilatora?

Obie konstrukcje są poprawne jeśli dajemy je świadomie, przy czym opcja A musi mieć ( (x = y) ), aby uniknąć ostrzeżeń.


VIX. Jaka jest wartość wyrażenia napisanego poniżej( w drugiej linijce).
bool ruch = false;
!!!ruch;

True


X. W wyrażeniu warunkowym instrukcji if może wystąpić nawet kilka operatorów logicznych. Załóżmy, że obiekty a, b, c są typu int. W poniższej instrukcji widzimy więc trzy człony alternatywy.
if((a < b ) || ( a < 15) || (a > (c = 15) ) { /*…*/ }
Pytanie 1: Który człon obliczony zostanie najpierw i jakie będą następne.
Pytanie 2: Wyjaśnij działanie członu trzeciego.
Pytanie 3. Oto instrukcja, która logicznie odpowiada powyższej

if( (a > ( c = 15) ) || (a < b ) || (a < 15) ) { /*…*/}
Wytłumacz jaka jest między nimi różnica, jeśli chodzi o końcową wartość obiektu c.

Pytanie 1: a < b, a < 15, c = 15, a > c
Pytanie 2: Człon trzeci najpierw przypisuję do c liczbę 15, a potem sprawdza czy a jest większe od c.
Pytanie 3: Tu na pewno c otrzyma wartość 15, w pierwszym wyrażeniu mogła nie dostać, jeśli któraś alternatywa zostałaby spełniona wcześniej


XI. To ćwiczenie jest na sprawdzenie zrozumienia różnicy między operatorami logicznymi a bitowymi. W tabelce podane mamy dwa obiekty(dla uproszczenia 16 bitowe) Podaj rozkład bitów wartości wyrażeń występujących w dalszej części tabeli.


Short int a; - 0000 1111 0000 1111
Short int b; - 0000 0000 0000 1111
Wypełnij rozkłady bitów dla poniższych wyrażeń
a & b - 0000 0000 0000 1111
a && b - 0000 0000 0000 0001
a | b - 0000 1111 0000 1111
a || b - 0000 0000 0000 0001


XII. Wyjaśnij działanie operatora += w poniższym fragmencie
int m = 3;
m += 2;
Podaj jaką wartość na skutek tych instrukcji będzie miał obiekt m.

Zwiększenie zmiennej m o 2( m = m +2 ), wartość końcowa = 5.


XIII. Na argumentach jakich typów pracuje operator przesunięcia w lewo(<<). Czym zapełniany jest bit z prawego brzegu słowa? Zerami czy jedynkami?
Co się dzieje z najbardziej znaczącym bitem?

Pracuje na całkowitych, prawy brzeg zapełniany jest zerami, najbardziej znaczący bit tracimy.


XIV. Napisz jak będzie wyglądał rozkład bitów w obiekcie rezultat po wykonaniu poniższych instrukcji.
short int a = 0xf (0000 0000 0000 1111)
short int rezultat = a << 2

0000 000 0011 1100


XV. Operator przesunięcia >> przesuwa bity danego słowa o żądaną ilość miejsc w prawo . Co, po przesunięciu, dzieje się z najmniej znaczącym bitem?

Tracimy go.


XVI. Jeśli chodzi o uzupełnianie bitów z lewej strony słowa przez operator >>, może to zależeć od implementacji. Są jednak sytuacje, gdy mamy pewność, że najbardziej znaczący bit będzie wypełniany zerami. Z jakim typem obiektu powinniśmy pracować, by mieć tę pewność?(Wiadomo, że musi to być obiekt typu całkowitego, ale z jakim „przydomkiem”?)

Unsigned, bądź signed dodatnie.


XVII. Jak zmieni się wartość obiektu x na skutek poniższych instrukcji?
int x = 0;
x =-1;
x -= 1;

x = -1
x = x – 1
x = -2


XVIII. Ile razy trzeba przesunąć w lewo bity poniższego obiektu by w rezultacie jego wartość została pomnożona przez 1024?
int ddd = 3;

ddd <<= 10


XIX. Załóżmy, że mamy obiekt typu int o nazwie x. Podaj wartość poniższego wyrażenia, gdy x = 100.
(x % 100) ? „Krakow” : „Londyn”

”Londyn”


XX. Mamy obiekt typu double o nazwie aaa. Które z poniższych wyrażeń jest poprawne?


A sizeof(aaa)
B sizeof(double)

C sizeof(double + 2)
D sizeof(double) + 2


XXI. Mamy obiekt typu double o nazwie mm. Napisz dwie formy zastosowania tzw. Tradycyjnego rzutowania tego obiektu na typ int. Na czym polega „stratność” takiego rzutowania?

(int)mm
Stracimy liczby po przecinku.


XXII. Co jest wartością następującego wyrażenia
(55.2 , 12, x++, a = b + 6, 4)

4


XXIII. Co to znaczy, że dany operator ma wyższy priorytet niż inny?

To znaczy, że zostanie wcześniej wykonany.


XXIV. Jak – nie pamiętając priorytetów operatorów – można mimo wszystko zapanować nad kolejnością obliczania danego skomplikowanego wyrażenia?

Za pomocą nawiasów.


XXV. Jaka jest łączność operatorów) jednoargumentowych?

Prawostronna


XXVI. Poniżej widzisz fragment kodu. Ostatnia instrukcja to przypisanie. Ujmij w nawiasy poszczególne człony tego przypisania – tak aby nawiasy nie zmieniły kolejności obliczania wyrażenia.
int a, b, c, d;
b = 15;
d = 2;
a = b = c = d

(a =( b = (c = d) ) ) Ostatecznie 2.


Jaka wartość ostatecznie znajdzie się w poszczególnych obiektach?
XXVII. Ujmij w nawiasy poszczególne człony wyrażenia mnożenia – tak, by nawiasy nie zmieniły kolejności obliczania wyrażenia.

int a, b, c, d, rezultat;
rezultat = a * b * c * d ;

( ( (a* B) * c ) * d)


XXVIII. Jaka jest łączność operatorów dwuargumentowych?

Lewostronna, jedynie przypisanie jest prawostronne.



5. Funkcje - Ćwiczenia

 


I. W danym miejscu programu wywołujemy funkcję f. Czy przed tym wywołaniem powinna wcześniej nastąpić definicja tej funkcji, czy deklaracja tej funkcji?

Deklaracja


II. Jak wygląda operator wywołania funkcji? To znaczy, czym różni się wywołanie funkcji od podania jej nazwy?

Operator: nazwafunkcji(), różni się nawiasami.


III. Przeczytaj następujące deklaracje funkcji. Które z nich są niepoprawne?


A int fa();
B void fb(int);
C void fc(void);

D double fd(int, void);
E Fe(double, char);
F void ff(double, int, int, char, int, int);
G void fb(int liczba);

H int fb(double wspolcz, int char znak);


IV. Mamy deklarację funkcji


int f();
a w ciele tej funkcji znajduje się instrukcja
return 4.2;
Jaką wartość zwróci funkcja f?

Zwróci wartość 4.


V. Mamy deklarację funkcji


double f2() ;
A w ciele tej funkcji znajduje się instrukcja
return 4;
Jaką wartość zwróci funkcja f2?

Zwróci wartość 4.0 .


VI. Co się stanie, jeśli w funkcji
void f5();
znajdzie się instrukcja
return 0;

Wystąpi błąd kompilacji.


VII. Czy poprawne są następujące deklaracje

A int man1();
B man2();
C int main();


Tylko A, jest poprawne.


VIII. Gdzie w programie jest deklaracja funkcji main ?

Definicja, jest równocześnie deklaracją.


IX. Mamy takie dwie realizacje funkcji main ?


int main()
{
return 1;
}
Oraz
int main()
{

}
Która z nich jest poprawna?

Obydwie.


X. W naszym programie, oprócz funkcji main mamy funkcje fff o następującym ciele


double fff()
{
int m = 6 +3;
main();
return 0,5 +m ;
}
Czy to poprawne?

Tak


XI. Funkcja main jest zdefiniowania w taki sposób
Int main()
{
return 33;
}
Gdzie dotrze wynik pracy tej funkcji?(liczba 33)

Do systemu operacyjnego, bądź programu, który potrzebował zwrotu tej liczby.


XII. Co to są argumenty formalne funkcji?

Argumenty, które funckja sobie "przezywa".


XIII. Co to są argumenty aktualne funkcji?

Te, które są wysyłane do funkcji.


XIV. Co to są argumenty wywołania funkcji?

Te same, co argumenty aktualne


XV. Oto dwie funkcje:


void pierwsza();
double druga(char z, int k)

void pierwsza()
{
// …
char cc = 'x'
int m = 8
double r = druga(cc, 7);
double y = druga('h', m);
}
Widzisz tu dwa wywołania funkcji druga. Dla obu przypadków wywołań wymień nazwy argumentów formalnych funkcji druga. Dla obu wywołań wymień jej argumenty aktualne.


Argumenty formalne funkcji druga: z, k
Argumenty aktualne:
double r: cc, 77
double y: 'h', m


XVI. Mamy dwie funkcje


void f1(int n)
{n++}
//-------
void f2(int &n)
{
n++;
}
Jaki otrzymamy wydruk na ekran pochodzący z poniższego fragmentu programu?
void g()
{
int liczba = 10 ;
f1(liczba);
cout << "liczba = " << liczba << endl;
f2(liczba);
cout << "liczba = " << liczba << endl;
}
liczba = 10
liczba = 11


XVII. Wymień dwa poznane dotychczas sposoby przesłania argumentów. Który może zmodyfikować wartość obiektu wysłanego do funkcji, a który nie?

Przez referencję oraz wartość. Przez wartość wysyła tylko kopie, a referencja posługując się "przezwiskiem" modyfikuje go.


XVIII. W programie składającym się z wielu plików, wielokrotnie używana jest funkcja mająca jeden argument domniemany typu double. Jego domniemana wartość to 7.5 Funkcja ta zdefiniowana jest w pliku zzz.cpp
Wiemy, że deklaracja tej funkcji musi się znaleźć w każdym pliku, który z tej funkcji zamierza skorzystać, (albo w jednym pliku nagłówkowym włączanym do wszystkich tych plików).
W którym miejscu programu powinna się znaleźć informacja o domniemaniu wartości tego argumentu?

Przed pierwszym użyciem tej funkcji.


XIX. Czy możliwa jest funkcja, która ma wszystkie argumenty domniemane?

Tak


XX. Czy możliwa jest funkcja, która ma domniemaną wartość rezultatu?

Tak.


XXI. Funkcja ma mięc dwa argumenty, z których jeden ma mieć wartość domniemaną, drugi jest zwykły. W jakiej kolejności mogą one wystąpić w deklaracji tej funkcji?

Najpierw zwykły, potem domniemany.


XXII. Dana jest funkcja
void f(int a, int b = 2, int c =3);
Można ją wywołać na przykład tak:
f(1, 2, 3);
Wymień wszystkie pozostałe możliwe sposoby wywołania tej funkcji nadające argumentom formalnym tę samą wartość, jaką nadaje powyższe wywołanie.

f(1); f(1,2)


XXIII. Napisz deklarację funkcji o nazwie fx, która zwraca rezultat typu bool, a wywoływana jest z dwoma argumentami. Pierwszy z nich jest typu char i jego wartością domniemaną jest 'g'. Drugi jest typu double i jego wartością domniemaną jest 12.5

bool fx(char y = 'g', double x = 12.5)


XXIV. Załóżmy, że poprawna jest deklaracja umieszczona poniżej w pierwszej linii. Czy poprawne jest wystąpienie zaraz za nią tych następnych w takiej właśnie kolejności? Jeśli nie, wskaż błędne.


A void f(int a, double, char c);
B void f(int a, double, char c = '2');
C void f(int a, double = 3, char c);

D void f(int a. double = 3, char = '6')


A, B, C są poprawne.


XXV. Czy poprawny jest następujący prosty program?


#include <iostream>
using namespace std;
void fun(int a, double B) { }
double x = 1.1;
double y = 8.8;
int main()
{
int zero = 0;

fun(1, 6.6);
{
void fun(int a = -1, double b = y);
fun();
if(2 > zero)
{
void fun(int a, double b = x ); fun(zero);
}
}
}
Jeśli nie, to dlaczego? Jak go poprawić, by jego działanie się nie zmieniło, ale dawał się kompilować poprawnie?

Nie kompilował się z powodu braku dostępu do zmiennej x, trzeba było ją zmienić aby była globalna jak wyżej.


XXVI. Czy możliwe jest, by funkcja, której deklaracja nie przewiduje żadnych argumentów domniemanych, w jakimś lokalnym zakresie miała zdefiniowane argumenty domniemane?

Tak, możemy ustalić lokalnie nowe argumenty domniemane, ale bedą tylko tu ważne.


XXVII. Jeśli zdecydowaliśmy, że jeden z argumentów formalnych funkcji f nie będzie w niej użyty, mimo, że inne funkcje tę funkcję f często z odpowiednim argumentem aktualnym wywołują, to gdzie należy zrobić zmianę określającą dany argument jako nienazwany? W definicji czy deklaracji funkcji?

W definicji.


XXVIII. W którym miejscu programu składającego się z jednego pliku – należy umieścić definicję funkcji inline? Jak postąpić, gdy program składa się z kilku plików?

Na samej "górze" programu, gdy program składa się z kilku plików trzeba umieści jej "zewnętrzną"(extern) deklarację w pliku nagłówkowym, bądź każdym pliku programu..


XXIX. Napisz program składający się z funkcji main i funkcji druga będących w dwóch różnych plikach. Następnie napisz definicję funkcji inline o nazwie wieksza, która przyjmuje dwa argumenty typu int, a jako rezultat zwraca większy z nich. Wywołania tej funkcji mają być zarówno z funkcji main, jak i z funkcji druga.
Zrób to na dwa sposoby:
1 używając pliku nagłówkowego włączanego dyrektywą #include,
2 bez użycia pliku nagłówkowego.


header.h



#include <iostream>

using namespace std;

inline int wieksza(int a, int B)
{
return (a > B) ? a : b;
}

void druga();


main.cpp



#include "header.h"

int main()
{
druga();
cout << wieksza(2, 3) << endl;

}


druga.cpp



#include "header.h"

void druga()
{
cout << wieksza(2, 3) << endl;
}




XXX. Jaki zakres ważności ma nazwa zdefiniowana w pliku programu poza wszelkimi funkcjami? Jak rozciąga się ten zakres ważności?

Globalny, rozciąga się od momentu zadeklarowania w dół, do końca programu.


XXXI. Porównaj zakres ważności nazw obiektów zdefiniowanych w ciele funkcji bez przydomka static i z przydomkiem static.

Taki sam - w ciele funkcji.


XXXII. Porównaj czas życia obiektów zdefiniowanych w ciele funkcji bez przydomka static i z przydomkiem static.

Wartość obiektów z przydomkiem static nie ginie po wyjściu z funkcji. Jest ona przechowywana i dostępna przy następnym wywołaniu funkcji. Jest definiowana tylko raz.
Wartość obiektów bez przydomka static ginie, przy każdym wykonaniu funkcji jest on definiowany na nowo, a po skończonej pracy usuwany.


XXXIII. Napisz program, w którym będzie funkcja void f();
Funkcja main ma wywoływać tę funkcję 100 razy. Funkcja f ma widzieć ile razy została wywołana i – przy co dwunastym wywołaniu – wypisywać na ekranie stosowny teskt(np. "nowy tuzin")


#include using namespace std;
void f()
{
static int licznik;
cout << "Jestem wywolana " << licznik << " raz!" << "\n";
if(!(licznik % 12)) cout << "Tuzin!\n"; licznik++;
}
int main()
{
for(int i = 0; i <= 100; i++)
f();
}


XXXIV. Czy poniższą funkcję uda się skompilować poprawnie?


int sumuj(int ile)
{
int sum;
for(int i = 0; i < ile ; i++)
{
sum += 1;
}
return sum;
}
Jeśli wywołamy ją tak: sumuj (4) - to czy można powiedzieć jaka będzie wartość zwracana przez nią?


Uda się skompilować, ale nie daliśmy zmiennej sum żadnej wartości, czyli przyjmie "śmieci" i nie wiadomo jaka będzie zwracana wartość(śmieci + 4)


XXXV. Mamy nastepujące obiekty: globalny, lokalny, automatyczny, statyczny. O których z nich można powiedzieć, że wstępnie inicjalizowane zerami; o których, że zawierają śmieci; a o których nic takiego nie można powiedzieć?


Globalny - inicjalizowany 0
Lokalny automatyczny - śmieci
Lokalny statyczny - śmieci
Statyczny - inicjalizowany 0


XXXVI. Używając dostępnego Ci kompilatora napisz, skompiluj i uruchom program, który będzie się składał z dwóch plików źródłowych *.cpp. W każdym z nich mają być po dwie funkcje - (main to też funkcja). Mają się tak wywoływać, by każda z nich pracowała choć raz. W każdym pliku mają być po trzy zmienne globalne typów int, double, char, (w sumie zatem będzie ich sześć).
Niech każda z funkcji tego programu:
- najpierw wypisze na ekranie wartość każdej z sześciu zmiennych globalnych,
- zmieni wartość ich wszystkich,
- ponownie wypisze na ekranie wartość każdej z sześciu zmiennych globalnych.
Posłuż się plikiem nagłówkowym *.h, w którym wystąpią potrzebne deklaracje.


header.h
extern int liczba1, liczba2;
extern double liczba3, liczba4;
extern char znak1, znak2;
void funkcja1();
void funkcja2();
void funkcja3();
jedynka.cpp
#include <iostream>
#include "header.h"
using namespace std;
int liczba1;
char znak1;
double liczba3;
int main()
{
funkcja1();
}
void funkcja1()
{
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2;
liczba1 = 20;
liczba2 = 40;
liczba3 = 0.2;
liczba4 = 0.4;
znak1 = 'K';
znak2 = 'o';
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2 << endl;
funkcja2();

return;
}
dwojka.cpp
#include <iostream>
#include "header.h"
using namespace std;
int liczba2;
char znak2;
double liczba4
;void funkcja2()
{
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2;
liczba3 += (liczba1 + liczba2);
liczba4 *= liczba3;
liczba1 += 10; liczba2 *= 30;
znak1 = 'n';
znak2 = 'r';
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2 << endl;
funkcja3();
return;
}
void funkcja3()
{
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2;
liczba3 += (liczba1 + liczba2);
liczba4 *= liczba3;
liczba1 += 10;
liczba2 *= 30;
znak1 = 'a';
znak2 = 'd';
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2 << endl;
return;
}


XXXVII. Mamy plik nagłówkowy z deklaracjami. Plik ten włączany jest dyrektywą #include w trakcie kompilacji kilku plików *.cpp naszego programu(jak w poprzednim zadaniu). Czy można w tym pliku nagłówkowym umieścić instrukcję:
extern int zmienna = 12;
Jaki odniesie to skutek? (Co na to kompilator? Co na to linker)

Nie można, kompilator zapewne potraktuje to jako zwykłą zmienną bez przydomka(zdefiniuje), a linker nic z nią nie zrobi.



6. Preprocesor

 


I. Jaki znak rozpoczyna dyrektywy preprocesora? Czy musi być pierwszym znakiem w linii?

# rozpoczyna dyrektywę preprocesora, nic nie może być.


II. Do czego służą tzw. Sekwencje trzyznakowe?(Nie musisz ich zupełnie znać, ale powinieneś przynajmniej wiedzieć, po co są)

Do wstawiania znaków niezbędnych w programowaniu, których nie mamy na naszej klawiaturze.


III. Wyjaśnij, co robi poniższa dyrektywa preprocesora:
#define A B 1 2

Pod A, podstawia „B 1 2”


IV. W programie są następujące dyrektywy:
#define LEWY_POKLAD 20
#define PRAWY_POKLAD 30
#define SSS LEWY_POKLAD + PRAWY_POKLAD
Co w związku, z tym wypisze na ekranie następująca instrukcja:
cout << (2 * SSS) << endl;
Masz jakieś uwagi krytyczne do tej ostatniej linijki?

Wypisze (2*20 + 30), czyli 70. Błąd krytyczny polega na braku nawiasach w makrodefinicji


V. Mamy takie fragment programu. Tylko jedna z poniższych instrukcji spowoduje błąd kompilacji. Która i dlaczego tylko ta jedna?
const int trzy = 3;
#define DZIESIEC 10;
//…

double s1 = trzy / DZIESIEC;
double s2 = DZIESIEC + trzy;

double s3 = DZIESIEC / trzy;

Błąd spowoduje linia zaznaczona na czerwono.


VI. Co zrobić, jeśli dyrektywa #define jest za długa, by się zmieściła w jednej linii programu?

Stosować backslashe(\), na końcu wyrazu linii.


VII. Powyższe ćwiczenia definiowały pewne stałe z pomocą dyrektyw preprocesora. Przepisz je modyfikując tak, by zamiast tych dyrektyw były stałe obiekty typu const. Czy poprzednie błędy(będące przedmiotem tych zadań) przeniosą się na ten nowy sposób? Który sposób wybrałbyś pisząc swój program?

const int LEWY_POKLAD = 20;
const int PRAWY_POKLAD = 30;
const int SSS = LEWY_POKLAD + PRAWY_POKLAD;
const int DZIESIEC = 10;
Nic się nie stanie, gdyż średnik oznacza koniec instrukcji. Wybiorę sposób z const, ponieważ kompilator jest w stanie dojrzeć mój błąd.


VIII. Czy można dwukrotnie dyrektywą zdefiniować tę samą nazwę?
#define NNN 10
//…
#define NNN 50
Co by musiało być między tymi dwoma powyższymi dyrektywami, by to było możliwe?

Tak, jedna zastąpi drugą.


IX. Mamy taką makrodefinicję:
#define DZIEL(a, B) (a/b)
Co pojawi się na ekranie na skutek instrukcji:
cout << DZIEL(2+3, 5.0) << endl;
Co należy poprawić w makrodefinicji, by na ekranie została wypisana wartość 1?

Wynikiem jest 2 + (3 / 5.0 ), należy dodać nawiasy.


X. Napisz makrodefinicję DZIEL(z poprzedniego ćwiczenia) w postaci funkcji inline pracującej na argumentach typu double.


inline double dziel(double a, double B) return (a / B);


XI. Mamy taki fragment programu:
#define CZYNNIK(a, B) ((a)/((a)+( B)))
int d = 0;
while(d < 10)
{
cout << „Czynnik = „ << CZYNNIK(++d, 2.0);
cout << „, dla d= „ << d << endl;
}

Ile razy wykonają się instrukcje pętli.(Czyli: ile będzie obiegów pętli?). Czy w makrodefinicji jest błąd?

Będzie 5 obiegów pętli, w makrodefinicji nie ma błędu.


XII. Zmień kod z powyższego zadania tak, by makrodefinicję czynnik zastąpiła funkcja(inline)
void CZYNNIK(double a, double B)
Ile razy wykona się wtedy pętla?

inline double CZYNNIK(double a, double b )return (a + (a/b));


XIII. Napisz makrodefinicję o nazwie MISJA, która przysłany do niej argument(np. „12”) zamieni na jeden wyraz np. Apollo_12. (Oczywiście jeśli argumentem będzie 9 to w rezultacie otrzymamy Apollo_9)

#define MISJA(a) Apollo_ ## a


XIV. Napisz makrodefinicję o jednym parametrze formalnym, która będzie wypisywała na ekranie:
- numer linii programu, w której ją wywołano,
- wyrażenie, które było jej argumentem(ma być ujęte w cudzysłów),
- wartość, tego wyrażenia.
To znaczy: jeśli w programie są dwa wywołania tej makrodefinicji(w linii 120 i 150), to na ekranie pojawić się powinien np. taki tekst:
W linii 120, wartosc wyrazenia „obiekt” = 12
W linii 150, wartosc wyrazenia „obiekt” = 0

#define WARTOSC(x) cout << „W linii „ << __LINE__ << „, wartość wyrazenia \”” << #x << „\” = „ << x << endl;


XV. Program ma mieć kilka wariantów. W tym celu posługujemy się kompilacją warunkową. Są już następujące dyrektywy preprocesora
#define GRUDZIEN_2007 1
#define SIERPIEN_2005 2
Potem jest dyrektywa, w której następuje wybór wersji. Poniżej widzisz, że wybrano tu akurat wersje „grudniową”
#define WERSJA_EKSPERYMENTU GRUDZIEN_2007
Potrzebujemy teraz dyrektywy #define TYP_SPREZARKI . . .
Powyżej, w miejscu wielokropka nazwa ta, w zależności od wybranego typu eksperymentu ma mieć wartości
- dla eksperymentu grudniowego: 3000
- dla eksperymentu sierpniowego: 2050
Jeśli zaś WERSJA_EKSPERYMENTU została określona inaczej lub nie została określona wcale, ma nastąpić przerwanie kompilacji i wydrukowany komunikat „Nieokreslony zostal typ eksperymentu”


#include <iostream>
using namespace std;

#define GRUDZIEN_2007 1
#define SIERPIEN_2005 2

#define WERSJA_EKSPERYMENTU GRUDZIEN_2007

int main()
{
#if( WERSJA_EKSPERYMENTU == GRUDZIEN_2007 )
#define TYP_SPREZARKI 3000
cout << "Typ sprezarki: " << TYP_SPREZARKI << endl;
#elif ( WERSJA_EKSPERYMENTU == SIERPIEN_2005 )
#define TYP_SPREZARKI 2050
cout << "Typ sprezarki: " << TYP_SPREZARKI << endl;
#else
#error "Nieokreslony typ eksperymentu";
#endif

}


XVI. Czy można zagnieżdżać dyrektywy preprocesora #if ?

Tak


XVII. Dyrektywa #ifdef ma podobne działanie jak defined. Kiedy używa się jednej, a kiedy drugiej? Która jest „bardziej samodzielna”?

#ifdef jest używana do sprawdzania czy nazwa została zdefiniowana. Defined trzeba użyć z #if i może występować z innymi warunkami. Bardziej samodzielna jest #ifdef, bo nie potrzebuje czegoś więcej do swego działania.


XVIII. Jakie jest działanie poniższych dyrektyw?
#include <plikA.h>
#include „plikB.h”

Pierwsza przyłączy plikA, którego szuka w folderze bibliotek kompilatora, a druga przyłączy plikB, którego szuka wzgłedem położenia programu.


XIX. Czy dyrektywy #include mogą być zagnieżdżane?

Tak, ale żaden plik nie może być przyłączany dwukrotnie. Jest to jednak możliwe z zabezpieczeniem.


XX. Czy poprawne jest złożenie takich dwóch dyrektyw?
#define PLIK <nazwa.h>
#include PLIK

Tak.


XXI. Napisz plik nagłówkowy, w którym będzie tylko jedna deklaracja funkcji. Ma być to funkcja o nazwie f zwracająca rezultat typu double, a wywoływana z dwoma argumentami typy int. Drugi argument ma wartość domniemaną równą zero. Deklaracja taka powinna zasadniczo pojawić się w kompilowanym programie tylko jednokrotnie.(Dlaczego?). Jak to zMPCarantować pisząc ten plik nagłówkowy?

#ifndef nagl
#define nagl
double f( int a, int b = 0);
#endif


XXII. Jaka jest różnica między tzw. Dyrektywą pustą (#), a operatorem preprocesora(#). Jest ryzyko nieporozumienia?

Obie są ignorowane, nie ma żadnego ryzyka.


XXIII. Pierwszy program z tej książki uzupełnij tak, by oprócz tekstu „Witamy na pokładzie” pojawiła się na ekranie informacja o tym:
1. Jak nazywa się plik programu,
2. W której jego linii nastąpiła instrukcja wypisująca,
3. Jaka była data kompilacji,
4. Jaka była godzina minuta, itd. tej kompilacji,
5. Czy użyto kompilatora C++.


#include <iostream>
int main()
{
std::cout << "Witamy na pokladzie, w pliku " << __FILE__
<< ", linii " << __LINE__
<< "\nData kompilacji: " << __DATE__
<< "\nGodzina kompilacji: " << __TIME__ << std::endl;

#ifdef __cplusplus
std::cout << "Skompilowane w kompilatorze C++" << std::endl;
#else
std::cout << "Skompilowane w czyms innym" << std::endl;
#endif
}



7. Tablice – Ćwiczenia

I. Czym się różni tablica 10 elementów typu int, od 10 obiektów typu int?

10 obiektów, się niczym ze sobą nie łączą, maja różną, a tablica jedna nazwa, z innymi indeksami. W tablicy obiekty leżą liniowo w pamięci inaczej są porozrzucane.


II. Czy można utworzyć tablicę 20 obiektów, z których pierwsze 10 będzie typu int, a następne 10 typu unsigned int?

Nie.


III. Mamy tablicę
unsigned int tab[200];
Przeczytaj tę deklarację. Jakiego typu obiekt oznacza nazwa tab?

Tablica 200 elementów typu unsigned int.


IV. Czy poprawne są poniższe definicje:
a) double wspolcz[5.6);
B) double fact[0];
c) signed int nomin[-6];

Nie.


V. Czy poprawna jest definicja tablicy:
int rozmiar = 10;
char tabl[rozmiar];

Tak. Np. gcc obsługuje VLA.


VI. Napisz definicję tablicy dwunastu elementów typu double.

double tab[12]


VII. Czy poprawna jest następująca definicja?
void tab[237];

Nie.


VIII. Napisz definicję typu wyliczeniowego ruch, który będzie przyjmował trzy wartości w_przod, w_tyl, stop. Następnie napisz definicję tablicy 15 elementów takiego typu. W tej definicji, za pomocą inicjalizacji zbiorczej nadaj pierwszym pięciu elementom tablicy jakieś wartości.

enum ruch { w_przod, w_tyl, stop } ruch tab[15]{ w_przod, w_tyl, w_przod, w_tyl, stop }


IX. Mamy definicję tablicy, w której można przechować tekst:
char alfabet[30];
Pamięć komputera zbudowana jest tak, że jej elementarne bity przyjmują tylko wartości 0 lub 1. Jak to więc możliwe, że tworzymy tablicę, w której można przechować litery?

Dzięki liczbie przyporządkowanej pod każdą z liter.(kod ASCII)


X. Co to jest znak null; po co jest potrzebny, skoro nie ma go w zwykłym alfabecie?

Jest to znak 0, potrzebny jest do oznaczania końca c-stringa.


XI. Napisz definicję tablicy 14 znaków, która jest od razu inicjalizowana c-stringiem "programowanie".

char tab[14] { "programowanie" }


XII. Napisz definicję tablicy 3 znaków, która od razu inicjalizowana jest odrębnymi znakami 'x', 'y', 'z'.

char tab[3] { 'x', 'y', 'z' }


XIII. Ile elementów ma tak zdefiniowana tablica
char tab[ ] = { "123" };
Jaka jest długość stringu w powyższej tablicy?

Ma 4 elementy, długość to 3.


XIV. Czym się różni długość stringu od rozmiaru stringu?

Długość, jest to liczba znaków, a rozmiar to liczba znaków + 1.


XV. Które z poniższych instrukcji są poprawne?
a) char tab1[4] = { "1,2,3" };
B) char tab2[] = {"1,2,3" };
c) char tab3[3] = { 'A', 'B', 'C' };

B) i c) dobrze.


XVI. Mamy tablicę
char tabl[10] = { " ABCD" };
Czy poprawne są następujące instrukcje korzystające z tej tablicy?

a) tabl[6] = 'm';
B) tabl[10] = { "GGGG"};
c) tabl[0] = { "GGGG"};
d) tabl[5] = { "a" };

e) tabl[0] = 'a';
f) tabl = '7';
g) tabl = "7"

Czerwony źle, zielony dobrze.


XVII. Mamy dwie tablice znakowe o identycznej długości. W jednej z nich znajduje się C-string. Napisz funkcje, która przekopiuje co drugą literę z jednej tablicy do drugiej. To znaczy: jeśli w jednej tablicy jest tekst "instytut", to w drugiej powinien się znaleźć C-string "isyu".


#include <iostream>
using std::cout;
void kopiowanie( char cel[], char zrodlo[])
{
for(int i = 0, k = 0; ; i += 2, k++)
{
cel[k] = zrodlo;
if(zrodlo == 0) break;
}
}

int main()
{
char napis1[20] = {"instytut"};
char napis2[20];

kopiowanie(napis2, napis1);
for(int i = 0; i < 20 ; i++)
{
cout << napis2;
if(napis2 == 0)break;
}
} [/color]


XVIII. Mamy tablicę znaków, w której znajduje się długi C-string będący tekstem, składającym się z kilkunastu wyrazów. Napisz funkcje, która przekopiuje ten C-String do dwóch innych tablic. W tablicy parzyste znaleźć mają się parzyste wyrazy C-stringu, a w tablicy nieparzyste – nieparzyste wyrazy C-stringu. W obu docelowych tablicach wyrazy mają być oddzielone odstępami(spacjami), czyli znakami ' '. Funkcja ta ma być wywoływana z trzema argumentami:
- adres tablicy źródłowej,
- adres tablicy na wyrazy parzyste,
- adres tablicy na wyrazy nieparzyste.


#include <iostream>
using namespace std;
void cpy_tekst(char src[], char parzyste[], char nieparzyste[])
{
bool spr = false;

for( int p = 0, n = 0, i = 0; ; i++)
{
if(src == 0) break;
if(spr == false)
{
nieparzyste[n] = src;
n++;
}
if(spr == true)
{
parzyste[p] = src;
p++;
}


if(src == ' ') spr = !spr;

}
}

void wrt_tekst(char tablica[])
{
for( int i = 0; ; i++)
{
if(tablica == 0)break;
cout << tablica;

}
}

int main()
{
char tekst[] = { "Approx jest noobem z MPCforum, ktory probuje programowac."};
char parzyste[100] = {"tekst"};
char nieparzyste[100] = {"tekst"};

cpy_tekst(tekst, parzyste, nieparzyste);
cout << "Parzyste wyrazy: ";
wrt_tekst(parzyste);
cout << endl << "Nieparzyste wyrazy: ";
wrt_tekst(nieparzyste);
cout << endl << "Cale zdanie: ";
wrt_tekst(tekst);

} [/color]


XIX. Wyjaśnij jakie ryzyko niesie w sobie instrukcja przypisania umieszczona w ciele poniższej pętli for.
char A[10];
char Z[10];
//…
for(int = 0 ; i < 10 ; )
{
A[i++] = Z[++];
}

Nie wiemy jaką wartość po którymś z rzędu obiegu przybierze zmienna.


XX. Czy poprawne jest poniższe wyrażenie warunkowe w instrukcji if
int a[10], b[10];
//…
if(a[6] = b[8])
{
cout << "Tekst";
}
Jakie musiały by być elementy tablic, aby na ekranie pojawił się powyższy tekst?

Jeśli tak było zamierzone to poprawne, ale lepiej dodać jeszcze nawiasy. b[8] musiałby być różny od zera.


XXI. Mamy dwie tablice
char t1[ ] = "Litwo, ojczyzno moja";
char t2[ ] = "ABC";
char t3[ ] = "123456789012345678901234567890"
Czy można string z tablicy t1 przepisać do tablicy t2? Czy można string z tablicy t1 przepisać do tablicy t3?

t1 do t2 – nie można
t1 do t3 – można, ale nadal zostaną cyfry.


XXII. Czy w funkcji, do której wysłano tablicę można dowiedzieć się ile ma ona elementów?

Nie.


XXIII. Napisz funkcję, która do końca stringu będącego w jednej tablicy, dołączy string, będący w drugiej tablicy. Argumentami tej funkcji powinny być
- adres tablicy docelowej,
- jej rozmiar,
- adres tablicy ze stringiem dołączanym.
Funkcja powinna przerwać dołączanie stringu w przypadku zapełnienia całej tablicy.


#include <iostream>
using namespace std;

void adder(char cel[], int rozmiar, char dolaczana[]);
void wypisywacz(char co_wypisac[], int rozmiar);
int main()
{
const int rozmiar = 50;
char tekst1[rozmiar] = { "Tekst, ktory sobie jest."};
char tekst2[rozmiar] = { "Tekst, ktory dolaczylem."};

cout << "To co jest: ";
wypisywacz(tekst1, rozmiar);
adder(tekst1, rozmiar, tekst2);
cout << endl << "To co zostalo dodane: ";
wypisywacz(tekst2, rozmiar);
cout << endl << "To co powstalo: ";
wypisywacz(tekst1, rozmiar);

}

void adder(char cel[], int rozmiar, char dolaczana[])
{
int poczatek;
for(int i = 0; i < rozmiar; i++)
{
if(cel == 0)
{
cel = ' ';
++i;
poczatek = i;
break;
}
}

for(int i = 0; poczatek < rozmiar; i++, poczatek++)
{
if(dolaczana == 0) break;
cel[poczatek] = dolaczana;

}
}

void wypisywacz(char co_wypisac[], int rozmiar)
{
for( int i = 0; i < rozmiar; i++)
{
cout << co_wypisac;
if(co_wypisac == 0) break;
}
} [/color]


XXIV. Napisz definicję tablicy 5 elementowej, której elementami są tablice 2 elementów typu float.

float tablica[5][2]


XXV. Mamy definicję
char[4][2][2];
Wypisz wszystkie elementy typu char tej tablicy w kolejności, w jakiej umieszczone są w pamięci komputera.


[0][0][0]
[1][0][0]
[2][0][0]
[3][0][0]
[0][0][1]
[1][0][1]

[2][0][1]
[3][0][1]
[0][1][0]
[1][1][0]
itd…


XXVI. Napisz program w którym będzie tablica dwuwymiarowa o rozmiarach: 10 rzędów i 3 kolumny. Do elementów zerowej kolumny załaduj kolejne liczby naturalne(i), do elementów następnej kolumny załaduj ich kwadraty(i*i), a do następnej sześciany (i*i*i).
Wypisz zawartość tej tablicy na ekranie – właśnie w postaci trzech pionowych kolumn.


#include <iostream>
using namespace std;

void wypelnijTab( int tablica[][10])
{
for(int i = 0, k = 0; i < 10, k < 3; i++)
{
tablica[k] = i;
if(i == 9)
{
i = -1;
k++;
}
}
}

void kwadrat( int tablica[][10])
{
for(int i = 0; i < 10; i++)
{
tablica[1] = i*i;
}
}

void szescian( int tablica[][10])
{
for(int i = 0; i < 10; i++)
{
tablica[2] = i*i*i;
}
}

void wypiszTab( int tablica[][10])
{
for(int i = 0; i < 10; i++)
{
cout << tablica[0] << "\t" << tablica[1] << "\t" << tablica[2] << "\n";
}
}

int main()
{
int potegi[3][10];
wypelnijTab(potegi);
kwadrat(potegi);
szescian(potegi);
wypiszTab(potegi);
}


XXVII. Zdefiniowaliśmy tablicę
double tab[10][5][30];
Które z rozmiarów tej tablicy są niezbędne do tego, by kompilator mógł obliczyć pozycję w pamięci jakiegoś z elementów tej tablicy? Jak myślisz, po co zatem potrzebny jest ten rozmiar, który nie jest konieczny do obliczania adres elementów?
Zdefiniowaliśmy tablicę
double tab[10][5][30]
W tekście programu mogą pojawić się na przykład następujące wyrażenia związane z tą tablicą.
tab[1][0][1], tab [6][4], tab [1], tab
Wyjaśnij co one oznaczają.

Najbardziej z lewej nie musi być podany, potrzebny jest aby określić ile wymiarów ma dana tablica.
tab[1][0][1] – 30 rzędów razy 5 kolumn +2, 152 element tablicy
tab[6][4] – 6 * 5 + 5 = 35 tablica 30 elementowa obiektów double
tab[1] – druga tablica 5 elementów będących tablicami 30 obiektów typu double
tab – tablica 10 elementowa, elementów będących tablicami 5 elementów, będących tablicami 30 elementow typu double



XXVIII. W programie mamy tablicę
double tab[10][5][30];
Napisz funkcję, która wyzeruje wszystkie elementy tej tablicy.


#include <iostream>
using namespace std;

void nullownia(double tab[][5][30])
{
for(int i = 0, y = 0, x = 0; ; x++)
{
if( x == 30) {x = 0; y++;}
if( y == 5) { y = 0; i++;}
if( i == 10) break;
tab[y][x] = 0;
}

}

void writer(double tab[][5][30])
{
for(int i = 0, y = 0, x = 0; ; x++)
{
if( x == 30) {x = 0; y++;}
if( y == 5) { y = 0; i++;}
if( i == 10) break;
cout << tab[y][x];
}
}

int main()
{
double tab[10][5][30];
nullownia(tab);
writer(tab);
}



XXIX. W układzie pomiarowym eksperymentu fizycznego dane przychodzą z 4 niezależnych kanałów o umownych nazwach FRS, GER, HEC, DGF. W trakcie pomiaru robiona jest statystyka równoczesności wystąpienia(czyli koincydencji) tych sygnałów. Polega to na tym, że jest tablica jednowymiarowa, w której kolejne elementy odpowiadając odpowiednim kombinacjom tych sygnałów. To znaczy na przykład element 3 odpowiada równoczesności sygnałów kanałach FRS i GER. Element 15 odpowiada równoczesności FRS, GER, HEC, DGF.
Oto odpowiednie kombinacje zebrane ww tabelkę
E0DEwEP.png
Zasada jest prosta – każdy sygnał ma jakby "swój" bit w numerze elementu. Obecność tego sygnału ustawia ten bit na 1, brak sygnału ustawia na 0. Po sprawdzeniu obecności lub nieobecności wszystkich 4 sygnałów powstaje słowo, będące numerem elementu w tablicy statystyki.
Skoro taka kombinacja właśnie wystąpiła to tenże element tablicy poddawany jest inkrementacji. (Czyli będący tam licznik takich sytuacji podwyższany jest o jeden).
To tyle tytułem wstępu.
Załóżmy, że pomiar trwa już jakiś czas i w tablicy są już jakieś liczby określające ile razy poszczególne kombinacje wystąpiły w ciągu tego czasu.
Teraz właściwe zadanie: napisz, która tę statystykę wyświetli na ekranie w taki mniej więcej sposób(wartości liczbowe są przykładowe).
Poszczegolne kombinacje wystąpiły nastepujaca ilosc razy
Kombinacja: FRS -> 346 razy
Kombinacja: GER -> 652 razy
Kombinacja: FRS + GER -> 737 razy
Kombinacja: HEC -> 277 razy
Kombinacja: FRS + HEC -> 444 razy
… itd. aż do kombinacji FRS + GER + HEC + DGF …
Jak widzisz jest to wypisanie kolejnych elementów tablicy, z tym że temu wypisowi towarzyszy opis kombinacji sygnałów. Gdyby jakaś kombinacja nie wystąpiła ani raz,(wartość = 0) wówczas oczywiście takiej linii statystyki nie wypisujemy.
Uwaga: Ten symboliczny opis kombinacji(no. "FRS + HEC + DGF") musi być konstruowany na bieżąco na podstawie analizy numeru elementu tablicy, który właśnie wypisujemy.
Opis ten nie może być więc "zaszyty" na stałe w programie. (Wyobraź sobie, że mamy nie 4 sygnały, ale 10 – musiałbyś wtedy przygotować 1024 takich gotowych tekstów).
Zatem twoje zadanie polega na tym, byś wypisując np. dwunasty element tablicy, potrafił opisać go na ekranie podając nazwy odpowiednich sygnałów. Gdy napiszesz tę funkcję i będzie działała poprawnie – pojawia się jeszcze jedno życzenie eksperymentatora.
Chciałby on mianowicie, aby wypisywane na ekranie kombinacje pojawiały się nie tak, jak są umieszczane w tablicy(po kolei), ale począwszy od najbardziej skomplikowanych kombinacji do najprostszych. Czyli by najpierw została linijka ze statystyką kombinacji 4 sygnałów, następnie linijki z różnymi kombinacjami 3 sygnałów, potem z kombinacjami 2 sygnałów, a na końcu sygnałów pojedynczych.
Czyli na przykład tak:
Poszczegolne kombinacje wystąpiły nastepujaca ilosc razy
Kombinacja: FRS + GER + HEC + DGF -> 346 razy
Kombinacja: FRS + GER + HEC - > 652 razy
Kombinacja: FRS + GER + DGF -> 737 razy
Kombinacja: FRS + HEC + DGF -> 277 razy
Kombinacja: GER + HEC + DGF -> 444 razy
… itd. aż do kombinacji FRS(pojedynczej)…


#include <iostream>
using namespace std;

void wyswietl(long int tab[], int rozmiar);

int main()
{
const int rozmiar = 16;
long int kombinacje_sygnalow[rozmiar];

// wypelnij(kombinacje_sygnalow, rozmiar);

wyswietl(kombinacje_sygnalow, rozmiar);

}
void wyswietl(long int tab[], int rozmiar)
{
cout << "Poszczegolne kombinacje wystapily nastepujaca ilosc razy:\n";

for(int i = 0; i < rozmiar; i++)
{
if(tab == 0) continue;

bool plus = false;
cout << "\nKombinacja: ";

if( (i/8) %2 )
{
cout << "DGF";
plus = true;
}


if ( i % 2)
{
if(plus) cout << " + ";
else plus = 1;

cout << "FRS";
}

if ( (i/4) % 2
{
if(plus) cout << " + ";
else plus = 1;

cout << "HEC";
}

if ( (i/2) % 2 )
{
if(plus) cout << " + ";
else plus = 1;

cout << "GER";
}

cout << " -> " << tab;

}

cout << endl;

}



Po ponad miesięcznej przerwie, którą miałem - big return ;)

8. Wskaźniki – Ćwiczenia

I. Wskaźnik o nazwie wsk został ustawiony tak, że pokazuje na obiekt o nazwie obj. Jaką zatem informację zapisano niniejszym do wskaźnika wsk?

Adres obiektu obj.


II. Zdefiniuj dwa obiekty: obiekt typu char oraz pokazujący na niego wskaźnik. Za pomocą wskaźnika przypisz do tego obiektu wartość ‘x’.

char litera;
char *wsk = &litera;
*wsk = ‘x’;


III. Oto linijka definicji:
unsigned long * a, b;
Jakie dwa obiekty są tutaj definiowane?(Wypowiedz ich pełne deklaracje).

Wskaźnik a, pokazujący na obiekty unsigned long.
Obiekt typu unsigned long


IV. Które z poniższych obiektów mogą być pokazywane wskaźnikami
a) zwykły obiekt
B) tablica obiektów
c) wskaźnik
d) referencja
e) nazwa
f) funkcja
g) komórka pamięci komputera
h) bit w komórce pamięci

Mogą: a), B), c), e), f), g).


V. Czy wskaźnik do pokazywania na obiekty typu char nadaje się do pokazania na obiekt typu double?

Nie.


VI. Kiedy mówimy, że wyrażenie jest l-wartością?

Wtedy, kiedy może stać po lewej stronie operatora.


VII. Czy l-wartość jest równocześnie r-wartością – czy odwrotnie?

l-wartość jest równocześnie r-wartością.


VIII. Mamy wskaźnik wsk pokazujący na jakiś konkretny obiekt. Które z poniższych wyrażeń są l-wartościami?
wsk
*wsk
&wsk

wsk, *wsk


IX. Zdefiniuj następujące obiekty
obj – obiekt typu char
wch1 – wskaźnik do obiektów typu char
wch2 – wskaźnik do obiektów typu char
wd – wskaźnik do obiektów typu double
Ustaw wch1 tak, by okazał na obj. Następnie ustaw wch2 tak, by pokazał na to samo, na co pokazuje wch1.
Co należy zrobić by możliwe było ustawienie wskaźnika wd tak, by pokazał na to samo miejsce w pamięci, na które teraz pokazuje wch2. Podaj dwa sposoby(„stary” i „nowy”).

 

char obj;
    char *wch1 = &obj;
    char * wch2 = wch1;
    double *wd = reinterpret_cast<double*>(obj);

 


X. Masz wskaźnik do obiektów typu int. Napisz instrukcję ustawiającą go tak, by pokazywał komórkę pamięci o adresie 0xa2ff4.
Napisz także najprostszą instrukcję ustawiającą go na adres 0x0000. Czym się różnią te instrukcje?

int *w = reinterpret_cast<int *>(0xa2ff4);
w = 0;
Ustawienie na 0, nie wymaga rzutowania.


XI. Napisz instrukcję wypisującą na ekranie adres, na który ustawiony jest bieżąco wskaźnik.

cout << wsk;


XII. Mamy dwa wskaźniki: double* oraz void*. Ustawione są one tak, że pokazują na ten sam obiekt typu double. Wyjaśnij w czym jeden z tych wskaźników jest lepszy od drugiego.

void* może pokazywać na każdy obiekt, ale nie wie jaki on jest(jaki ma typ), a double „wie na co pokazuje”.


XIII. Mamy obiekt typu char, o nazwie cc, i wskaźnik void* o nazwie wv. Napisz definicję tego wskaźnika wv połączoną z inicjalizacją go tak, by pokazywał na ten obiekt cc. Zdefiniuj wskaźnik do typu char o nazwie wc. Ustaw go tak, by pokazywał na to samo, na co pokazuje wskaźnik wv.


char cc = ‘x’;
void *wv = &cc;
char *wc = reinterpret_cast<char*>(wv);


XIV. Mamy tablicę znaków zawierającą litery alfabetu ABCDEFGHIJKLMNOPQRSTUWVZ.
Zdefiniuj wskaźnik i ustaw go na drugim elemencie tablicy.
Począwszy od tego miejsca – za pomocą pętli i przesuwania tego wskaźnika – wypisuj na ekranie co czwartą pokazywaną literę, dopóki znak nie będzie miał kogo ASCII większego lub równego kodowi litery Z.


#include <iostream>
using namespace std;
int main() {
char alfabet[] = {"ABCDEFGHIJKLMNOPQRSTUWVZ"};
for( char *wsk = &alfabet[1]; *wsk <= 'Z' ; wsk += 4) cout << *wsk;
}


XV. Mamy tablicę znaków oraz wskaźnik pokazujący na jakiś jej element. Jak – jedną instrukcją – sprawić, by wskaźnik ten pokazał o 6 elementów dalej? Czy możliwe jest przesunięcie o 100 elementów dalej, mimo że tablica jest tylko 90 elementowa?

wsk += 6 . Możliwe, bo wskaźnik nie sprawdza poprawności przesuwania.


XVI. Jeśli mamy wskaźnik pokazujący na piąty element tablicy znaków, a przesuniemy go tak, by przesunął się o 30 miejsc, w stronę początku – jak na to zareaguje kompilator. Kiedy, jeśli w ogóle, objawi się taki błąd?

Kompilator w ogóle na to nie zareaguje, dopiero gdy będziemy chcieli odczytać coś z tej komórki, a ona będzie zniszczona.


XVII. Jak wiadomo, obiekty różnych typów mogą w pamięci zajmować różną ilość komórek(słów czy bajtów). Mamy dwie tablice
char tC[10];
long tL[10];
Napisz definicję odpowiednich wskaźników i ustaw je tak, by pokazywały na początek tych tablic. Napisz instrukcję przesuwające oba te wskaźniki o 4 elementy tablicy dalej.

char wc = tC;
long wl = tL;
wc += 4;
wl += 4;


XVIII. Mamy tablicę o nazwie kalibracja. W programie potrzebujemy jej adresu. Jak go uzyskać?

Za pomocą referencji, albo jej nazwy(nazwa jest równocześnie adresem jej zerowego elementu.


XIX. Czym się różni nazwa tablicy od wskaźnika ustawionego na jej zerowy element?

Nazwa zawsze będzie pokazywała adres tej tablicy, a wskaźnik można przesunąć.


XX. Mamy tablicę i dwa wskaźniki
double tab[50];
double *wskA = &tab[10];
double *wskB = &tab[40];
Podaj wartość wyrażenia (wskB – wskA). Podaj wartość wyrażenia( wskA – wskB).

wskB – wskA == 30
wskA – wskB == -30


XXI. Załóżmy, że mamy wskaźniki pokazujące na tę samą tablice. Które z poniższych operacji na tych wskaźnikach mają sens?
a) dodawanie dwóch wskaźników
B) dodawanie liczby całkowitej do wskaźnika
c) odejmowanie dwóch wskaźników
d) odejmowanie liczby całkowitej od wskaźnika
e) mnożenie dwóch wskaźników
f) mnożenie wskaźnika przez liczbę całkowitą
h) dzielenie dwóch wskaźników
i) dzielenie wskaźnika przez liczbę całkowitą

B), c), d) są z sensem


XXII. Mamy dwa wskaźniki pokazujące na tę samą tablicę. Wyjaśnij, jaką informację otrzymujemy wykonując na nich operacje następującymi operatorami:
== != < > <= >=

== czy pokazują na to samo
!= czy pokazują na różne obiekty
< czy adres jest „mniejszy” od drugiego
> czy adres jest „większy” od drugiego
<= czy adres jest „mniejszy”, bądź pokazuje na to samo co drugi
>= czy adres jest „większy”, bądź pokazuje na to samo co drugi


XXIII. Mamy dwa wskaźniki pokazujące na zupełnie różne obiekty. Czego dowiadujemy się wykonując na tych wskaźnikach operacji porównania (np. <)?

Gdzie znajdują się one w pamięci.


XXIV. Wskaźniki w trakcie swej definicji nie zostały przez nas zainicjalizowane. Na co pokazują wstępnie?
a) wskaźnik będący lokalnym obiektem automatycznym,
B) wskaźnik będący lokalnym obiektem statycznym,
c) wskaźnik będący obiektem globalnym,
d) wskaźnik z przestrzeni nazw(namespace).

automatyczny – na śmieci
statyczny – na 0
globalny – na 0
przestrzeń nazw – na 0


XXV. Jaki cel ma ustawienie wskaźnika na adres 0?

Żeby pokazać, że nie pokazuje na nic przydatnego.


XXVI. Jak najkrócej sprawdzić instrukcją if czy wskaźnik jest ustawiony na adres zerowy?

if(!wsk)


XXVII. Jak najkrócej sprawdzić instrukcją if czy wskaźnik jest ustawiony na adres inny niż zerowy?

if(wsk != 0)


XXVIII. Załóżmy, że mamy wskaźnik o nazwie wsk. W starszych programach możesz spotkać się z zapisem
if(wsk != NULL)..
Co on oznacza? Jak to samo zapisać bez użycia(makrodefinicji) NULL?

Czy na coś pokazuje, inaczej if(wsk != 0)


XXIX. Napisz funkcję o nazwie zerowanie, która odbierać będzie argument będący wskaźnikiem do int i do tak pokazywanego obiektu wpisze zero. Następnie napisz prosty program, w którym będzie tablica obiektów typu int. Za pomocą tej funkcji dokonaj zerowania wybranych kilku elementów tej tablicy. Na przykład niech to będą elementy nr. 0, 3, 4, 7


void zerowanie(int *wsk){
*wsk = 0
}
int main(){
int tablica[10];
zerowanie( tablica);
zerowanie( &tablica[3]);
zerowanie( &tablica[4]);
zerowanie( &tablica[7]);
}


XXX. Napisz prosty program mający funkcje, do której można będzie wysłać tablicę typu int. Funkcja ta ma do każdego elementu tej tablicy dodać liczbę 44. W funkcji main tego programu zdefiniuj lokalną tablicę, a następnie wobec tej tablicy zastosuj tę funkcję dodającą – raz wobec wszystkich elementów tej tablicy, drugi raz wobec pierwszych 5 elementów.


void dodajemy( int tab[], int ile){
for(int i = 0; i < ile; i++) tab += 44;
}
int main(){
int tab[] = {1,2,3,4,5,6,7,8,9,10};
dodajemy(tab, 10);
dodajemy(tab, 5);
}


XXXI. W programie mamy tablicę stałych typu double. Napisz funkcję, która pokaże na ekranie zawartość tej tablicy.


void pokaz( const double *wsk, int ile){
for(int i = 0; i < ile; i++) cout << wsk;
}
int main(){
const double tab[] = {1,2,3,4,5,6,7,8,9,10};
pokaz(tab, 10);
}


XXXII. Tworzymy operatorem new obiekt(typu wbudowanego) i nie inicjalizujemy go żadną wartością. Co zawiera wstępnie tai obiekt? Czy pod tym względem przypomina bardziej obiekt globalny czy automatyczny?

Śmieci, automatyczny.


XXXIII. Napisz program, w którym w funkcji main zostaną stworzone(operatorem new) trzy tablice typu double o rozmiarach co najmniej 20 elementów. Elementy pierwszych dwóch tablic załaduj jakimiś wartościami. W programie powinna być funkcja, która przyjmie wysłane do niej te trzy tablice. Funkcja ta ma na elementach tych tablic wykonać operację mnożenia – taką, że i-ty elementu tablicy pierwszej zostanie pomnożony przez i-ty element tablicy drugiej. Rezultat ma być wpisany do i-tego elementu tablicy trzeciej.
W funkcji main wypisz na ekran zawartość poszczególnych elementów tablicy pierwszej, drugiej i trzeciej, a następnie skasuj te tablice.


#include <iostream>
using namespace std;

void mnozenie(double *wsk1, double *wsk2, double *wsk3){
for(int i = 0; i < 20; i++)
wsk3 = wsk1 * wsk2;
}

int main(){
double *wsk1, *wsk2, *wsk3;
wsk1 = new double[20];
wsk2 = new double[20];
wsk3 = new double[20];

for(int i = 0; i < 20; i++)
wsk1 = i;
for(int i = 0; i < 20; i++)
wsk2 = i;

mnozenie(wsk1, wsk2, wsk3);
for(int i = 0; i < 20; i++)
cout << wsk3 << "\n";
delete[] wsk1;
delete[] wsk2;
delete[] wsk3;
}


XXXIV. Zmodyfikuj powyższy program tak, by teraz tworzeniem każdej tablicy zajęła się funkcja o nazwie kreator_tablicy. Jedno wywołanie tej funkcji ma tworzyć jedną tablice, a argumentem aktualnym(wywołania) tej funkcji powinien być żądany rozmiar danej tablicy.


#include <iostream>
using namespace std;

double* kreator_tablicy(int rozmiar){
double *wsk = new double[rozmiar];
return wsk;
}

void mnozenie(double *wsk1, double *wsk2, double *wsk3){
for(int i = 0; i < 20; i++)
wsk3 = wsk1 * wsk2;
}

int main(){
double *wsk1, *wsk2, *wsk3;
wsk1 = kreator_tablicy(20);
wsk2 = kreator_tablicy(20);
wsk3 = kreator_tablicy(20);

for(int i = 0; i < 20; i++)
wsk1 = i;
for(int i = 0; i < 20; i++)
wsk2 = i;

mnozenie(wsk1, wsk2, wsk3);
for(int i = 0; i < 20; i++)
cout << wsk3 << "\n";
delete[] wsk1;
delete[] wsk2;
delete[] wsk3;
}


XXXV. Wyjaśnij jaka jest różnica między poniższymi instrukcjami
int *wsk1 = new int[10];
int *wsk2 = new int(10);

Pierwsza tworzy tablicę 10elementową, a druga obiekt który jest wstępnie inicjalizowany wartością 10.


XXXVI. W poprzednim ćwiczeniu zobaczyliśmy dwie instrukcję, w których występuje słowo kluczowe new. Czy mamy tu do czynienia z dwoma wersjami składni tego samego operatora, czy też są to dwa odrębne operatory? Napisz instrukcje kasujące obiekty zdefiniowane w taki sposób. Czy użyć musisz tego samego operatora, czy dwóch odrębnych?

Dwie odrębne wersje.
delete[] wsk1;
delete wsk2;


XXXVIII. Jaka jest nazwa obiektu stworzonego poniższą instrukcją?
double *wsk = new double;

Nie ma nazwy, można się odnieść do niego wskaźnikiem.


XXXIX. Wymień trzy sposoby, w jakie operator new może powiadomić nas o niemożliwości stworzenia nowego obiektu na skutek wyczerpania zapasu dostępnej pamięci. Który z nich jest zalecany?

Zwracanie adresu 0, rzucenie Bad_alloc, własne powiadomienie set_new_handler


XL. Jaka jest różnica między wskaźnikiem stałym, a wskaźnikiem do obiektu stałego?

Wskaźnika stałego nie można przesunąć, a wskaźnik do obiektu stałego nie potrafi zmienić wartości obiektu na który pokazuje.


XLI. Czy może istnieć wskaźnik stały do obiektu stałego?

Tak


XLII. Kiedy można wpisywać adres do wskaźnika stałego?

Podczas inicjalizacji


XLIII. Mamy definicje następujących obiektów:
int *const wa = new int;
const int *wb = new int(8);
int m = 4;
Które z poniższych instrukcji kompilator odrzuci i dlaczego?
a) wa = 10;
B) wb= 10;
c) *wa = 10;
d) *wb = 10;
e) wa = &m;
f) wb = &m;
g) delete wa;
h) delete wb;
Które z tych instrukcji(traktowanych oddzielnie) są bardzo ryzykowne, mimo że kompilator nie zaprotestuje?

Przyjmie: c), f), g), h)
Odrzuci: a) nie można zmienić adresu wskaźnika stałego
B) nie można zmienić adresu na 10 bez użycia rzutowania
d) nie można przypisać nowej wartości obiektowi stałemu
e) nie można zmienić adresu wskaźnika stałego

f) jest dość ryzykowne, bo moglibyśmy usunąć obiekt m później za pomocą delete.


XLIV. Poniżej widzimy dwa fragmenty kodu. Oba nie wywołają błędu kompilacji. Czy są, mimo to, poprawne? Wyjaśnij co powodują oba fragmenty.
a) int *wsk;
*wsk = 0;
B) int *wsk = 0;

*wsk = 0 – zmieni przypadkową wartość na 0, bo wskaźnik jest automatyczny i pokazuje na nie wiadomo co
int *wsk = 0, ustawi wskaźnik na adres zerowy.


XLV. Mamy zapis:
const char *wsk = „Napis”;
Co tu jest definiowane?

wskaźnik do c-stringu.


XLVI. Mamy następujące obiekty
int obiekt = 100;
int *intw;
const int *Cintw;
int * const intCw = &obiekt;
const int * const CintCw = &obiekt;
Jak widzisz nazwy są wybrane tak, by przypominały o typie obiektu. Np. Cintw – to skrót od const int wskaźnik.
Które z poniższych instrukcji zostaną przez kompilator odrzucone jako błędne i dlaczego?
a) intw = Cintw;
B) intw = intCw;
c) intw = CintCw;
d) Cintw = intw;
e) Cintw = intCw;
f) Cintw = CintCw;
g) CinCtw = intw;
h) CintCw = Cintw;
i) CintCw = intCw;
Które z powyższych przypisań można przeprowadzić dzięki operacji rzutowania, a które są niemożliwe nawet za pomocą rzutowania?

Poprawne: b, d, e, f. Za pomocą rzutowania: a), g), h), i)


XLVII. Napisz definicję 100-elementowej tablicy wskaźników do obiektów typu unsigned char.

unsigned char *(tab[100])


XLVIII. Napisz funkcję, która zarezerwuje 10 elementową tablice, a jej adres przekaże wskaźnikowi o nazwie linijka. Ma to być tablica w której można przechowywać wskaźniki do tablic znaków.
Następnie za pomocą pętli for dla każdego z 10 elementów tej tablicy linijka:
- zarezerwuj operatorem new tablice 80 znaków
- jej adres wpisz do kolejnego elementu tablicy linijka.
- w tej 80 znakowej tablicy umieść C-string „to jest linijka nr n” – gdzie n jest kolejnym numerem linijki(0 – 9).
Po zrobieniu tego wobec wszystkich 10 elementów tablicy linijka, za pomocą pętli for wypisz na ekranie kolejno zawartość tych C-stringów.
W tablicy wskaźników linijka dokonaj takiej zamiany, by zamienić naszych zawartość elementu trzeciego z szóstym.
Za pomocą takiej samej jak poprzednio pętli for, wypisz na ekranie naszych 10 C-Stringów.
Zlikwiduj wszystkie rezerwowane operatorem new obiekty.

// Nie mojego autorstwa
#include <iostream>
using namespace std;

char ** zarezerwuj(int rozmiar);
void kopiuj_indeks(char * w1, int ktory);

int main()
{
int rozmiar = 10;
char * *linijka = zarezerwuj(rozmiar); //skoro ma pokazywać na tablicę wskaźników, sama musi być wskaźnikiem do wskaźników

for(int i = 0; i < 10; i++, linijka++)
{
*linijka = new char [80]; // *linijka - to na co pokazuje linijka, czyli wskaźnik do char
kopiuj_indeks(*linijka, i); // Wysylamy adres zerowego elementu tablicy i indeks, który będzie dopisany
}
linijka -= 10; // Resetujemy wskaźnik, bo poprzednia pętla przesunęła go na koniec tablicy


for(int i = 0; i < 10; i++)
{
cout << *(linijka++) << endl; // Drukujemy po kolei to na co wskazuje wskaźnik, czyli wskaźniki, ale one pokazują na początek tablic stringów,
//czyli to tak jakbyśmy wpisali nazwę tablicy
}
linijka -= 10; // i znowu musimy go zresetować

char *wsk = linijka[3]; // Teraz robimy zadaną zamianę
linijka[3] = linijka[6];
linijka[6] = wsk;

// Drukujemy ponownie
cout << endl;

for(int i = 0; i < 10; i++)
{
cout << *linijka++ << endl;
}
linijka -= 10; // reset


for(int i = 0; i < 10; i++, linijka++)
{
cout << *linijka << endl; // Tak dla kontroli drukujemy to co za chwilę skasujemy
delete [] *linijka; // kasujemy to na co pokazuje wskaźnik linijka, czyli wskaźnik do tablicy utworzonej operatorem new
*linijka = 0; // I jak mistrz Grębosz zalecił, zabezpieczamy nasz pistolet, żeby przypadkiem nie wypalił
}
}
//**********************************************************************************************************************************************
char ** zarezerwuj(int rozmiar) // ** bo to funkcja zwraca wskaźnik, mogący pokazywać na wskaźniki, bo wskaźnikami właśnie są elementy utworzonej tablicy
{
char ** wsk;
wsk = new char * [rozmiar]; // Nie rozumiem, po co odrazu do tego funkcje pisać. Operator new uważam, za bardzo wyraźny i wygodny
return wsk;
}
//**********************************************************************************************************************************************
void kopiuj_indeks(char * w1, int ktory)
{
char tab[21] = {"To jest linijka nr. "}; // String, który będzie wpisywany zawsze
char * w2 = tab; // i wskaźnik do wygodnego nim operowania

for(int i = 0; i < 20; i++)
{
*(w1++) = *(w2++);
}

*(w1++) = ('0' + ktory); // Tutaj tworzymy cyfrę, jeśli to jest pętla z i = 0, to wpisze się 0, potem 1 itd
*w1 = 0; // A na koniec oczywiście 0 konczace string

}


IL. Napisz deklarację funkcji, która przyjmuje dwa argumenty. Pierwszy będący C-stringiem, a drugi będący wskaźnikiem do tablicy wskaźników do obiektów typu double. Funkcja ma zwracać wskaźnik do typu void.

void* funkcja(char *napis, double *(*tablica))


L. Napisz funkcję, która wywoływana jest z dwoma argumentami. Pierwszy to wskaźnik do tablicy znaków, w które jest już jakiś C-string. Drugi to rozmiar tej tablicy. Funkcja ta ma do początku bieżącej treści tablicy znaków dopisać tekst „UWAGA: „ ,
Jeśli w rezultacie powstałby C-string dłuższy, niż na to pozwala obecny rozmiar tablicy znaków – niech trzy ostatnie możliwe znaki zostaną zastąpione trzema kropkami.
Jako rezultat swej pracy funkcja ta ma zwracać wskaźnik do tablicy znaków, na której dokonała zmiany.

// Nie mojego autorstwa
#include <iostream>
using namespace std;

char * funkcja (char * string, int rozmiar);

int main()
{
const int rozmiar = 53;
char tekst[rozmiar] = {"Total War to zaprawde wybitna seria strategiczna."};

funkcja(tekst, rozmiar);

cout << tekst << endl;

}

//***********************************************************************

char * funkcja (char * const pstring, const int rozmiar)
{
// Definicje potrzebnych wskaźników
char * const pschowek = new char [rozmiar]; // Te stałe wskaźniki posłużą do resetowania wskaźników, które będziemy przesuwać
char * schowek = pschowek;
char * string = pstring;

// Kopiowanie stringa do schowka
for( ; ; schowek++, string++)
{
if( !(*schowek = *string) ) break;
}
schowek = pschowek;
string = pstring;

{ // Wpisywanie stringu "Uwaga: "
char uwaga[8] = {"Uwaga: "};
char * wsk = uwaga;
for(int i = 0; i < 7; i++) // Ósme jest zero, a nie chcemy go skopiować, bo to jeszcze nie koniec stringu
{ // Dlatego pętlę wykonujemy 7 razy
*(string++) = *(wsk++);
}
// Tym razem nie resetujemy wskaźnika string, bo chcemy, żeby był ustawiony na koniec uwagi
}

// Finalne dopisanie do "uwaga: " tego co mieliśmy w schowku, czyli stringa, który nam przysłano
for(int i = 7 ; ; i++, string++, schowek++ ) // i posłuży do sprawdzenia, czy nie przekraczamy rozmiaru
{
if( i == rozmiar ) // Jak już mamy wpisać do tablicy coś o indeksie jej rozmiaru, czyli tam gdzie już jej nie ma to:
{
string -= 4; // Cofnij się o 4
for(int i = 0; i < 3; i++) // W trzy kolejne elementy wpisz kropki
{
*(string++) = '.';
}
*string = 0; // A w następny 0
break; // I wyjdź
}

if( !(*string = *schowek) ) break;

}

delete [] pschowek; // sprzątamy po sobie

return pstring;
}


LI. Przeczytaj poniższe deklaracje:
void(*w)(void);
void *(*w)(void*);
int(*w)(int, double, char*);
double(*w)(int, double, char*);

w – wskaźnik służący do pokazywania na funkcję wywoływane bez żadnych argumentów i niezwracających żadnego obiektu.
w – wskaźnik pokazujący na funkcje, której argumentem jest wskaźnik typu void i zwraca wskaźnik typu void.
w – wskaźnik na funkcje, której argumentami są, int, double i wskaźnik do char, a zwracającą obiekt typu int
w – wskaźnik pokazujący na funkcję, której argumentami są, int, double i wskaźnik do char, a zwracającą obiekt typu double.


LII. Napisz definicję wskaźnika, który może pokazywać na funkcję wywoływaną z argumentem typu wskaźnik do tablicy znakowej, a zwracająca rezultat typu wskaźnik void.
void* (*w)(char *)
LIII. Napisz deklarację funkcji, która otrzymuje dwa argumenty, a zwraca rezultat typu bool. Argumentami tej funkcji są:
1. wskaźnik do funkcji wywoływanej z dwoma argumentami typu double, a zwracający rezultat typu bool.
2. wskaźnik do funkcji wywoływanej z jednym argumentem typu double, a zwracającej rezultat typu char.

bool (*w)( bool (*wsk)(double, double), char(*wsk2)(double) )


LIV. Napisz krótki program, w którym będą trzy funkcję wywoływane bez żadnych argumentów, a zwracjące rezultat typu int.
Zdefiniuj dodatkową funkcje F, do której wyślesz adres jednej z tych funkcji. Funkcja F ma wywoływać funkcję, której adres otrzymała, a następnie jej rezultat zwrócić jako swój rezultat.


#include <iostream>
using namespace std;
int funkcja1(){
cout << "Jestem w funkcji nr 1 ";
return 1;
}
int funkcja2(){
cout << "\nJestem w funkcji nr 2 ";
return 2;
}
int funkcja3(){
cout << "\nJestem w funkcji nr 3 ";
return 3;
}

int F( int (*wskaznik)() ){
int zwrot = wskaznik();
return zwrot;
}

int main(){
cout << F(funkcja1);
cout << F(funkcja2);
cout << F(funkcja3);
}


LV. W poprzednim zadaniu wystąpiła funkcja F. Napisz definicję wskaźnika mogącego pokazywać na taką funkcję.


int (*w)( int(*)());


LVI. Czy wskaźnikiem typu (double *) można pokazać na funkcję double* f() ?

Nie


LVII. Mamy nazwę funkcji. Jakim operatorem można spowodować jej wywołanie?

()


LVIII. Czytając deklarację wskaźnika do funkcji rozpoczynamy od przeczytania jego nazwy, a następnie zaczynamy posuwać się w prawo. Dlaczego w prawo, a nie w lewo?

Bo tam są najmocniejsze operatory.


LIX. Czy na funkcję z argumentem domniemanym
void f(int m = 4);
można pokazać wskaźnikiem void (*w)();

Nie


LX. Jakie operacje arytmetyczne można przeprowadzać na wskaźnikach do funkcji?

Żadne, nie ma to sensu.


LXI. Czy do wskaźnika do funkcji wolno przypisać zero?

Tak


LXII. Czy argument formalny funkcji będący wskaźnikiem do innej funkcji może mieć wartość domniemaną?

Tak


LXIII. Napisz program imitujący pracę robota przemysłowego. Powinien mieć on sześć funkcji odpowiadających za elementarne ruchy robota.
Wszystkie te funkcje powinny być wywoływane bez żadnego argumentu, a zwracać rezultat typu bool.
Ich ciało zawierać powinno wypis na ekran wyjaśniający co dana funkcja, robi. Na przykład funkcja bool obrot_w_prawo() powinna wypisać na ekranie tekst "Obrot ramienia w prawo".
Wartość rezultatu ma służyć, że operacja się powiodła w naszym przypadku - zawsze niech będzie zwracana wartość true.
Niech gdzieś w funkcji main pojawi się menu pozwalające wybrać jedną z sześciu operacji. Po wybraniu jednej z tych operacji adres odpowiedniej funkcji powinien zostać zapisany w tablicy wskaźników do funkcji.
W ten sposób powinno się zapamiętywać skomplikowaną operację składającą się z maksymalnie 20 ruchów robota.
W menu powinna być komenda "wykonać", na skutek której wszystkie operacje, w kolejnosci w jakiej były wybierane z menu i składowane w tablicy, powinny zostać wykonane(czyli ich funkcje uruchomione).
Jeśli w menu wybierze się komende "koniec" - program się kończy.


#include <iostream>
using namespace std;

bool krokDoTylu(){
cout << "Przesuwam sie do tylu" << endl;
return true;
}

bool krokDoPrzodu(){
cout << "Przesuwam sie do przodu" << endl;
return true;
}

bool ObrotPrawy(){
cout << "Obracam ramie w prawo" << endl;
return true;
}

bool ObrotLewy(){
cout << "Obracam ramie w lewo" << endl;
return true;
}

bool wDol(){
cout << "Opuszczam w dol" << endl;
return true;
}

bool doGory(){
cout << "Podnosze do gory" << endl;
return true;
}

int main(){

short int ktory;
bool (*co[20])();
cout << "-Robot Przemyslowy-";
for(int i = 0; i < 21; i++){
cout << "\n 1. Krok do przodu";
cout << "\n 2. Krok do tylu";
cout << "\n 3. Obrot w prawo";
cout << "\n 4. Obrot w lewo";
cout << "\n 5. Opuszczenie";
cout << "\n 6. Podniesienie";
cout << "\n 7. Wykonaj\n";

cin >> ktory;
switch(ktory){
case 1:
co = &krokDoTylu;
break;
case 2:
co = &krokDoPrzodu;
break;
case 3:
co = &ObrotPrawy;
break;
case 4:
co = &ObrotLewy;
break;
case 5:
co = &wDol;
break;
case 6:
co = &doGory;
break;
case 7:
for(int j = 0; j < i; j++){co[j]();}
break;
default:
cout << "Nie ma takiej opcji";
break;
}
cout << "Petla nr" << i << endl;
}
}


LXIV. Mając powyzszy program zamień go na taki, w którym poszczególne funkcje odpowiadające za elementarne ruchy robota wywołane są z argumentem typu double. W trakcie swej pracy, funkcja powinna wypisać jego wartość na ekranie. (np. "Obrot ramienia w prawo o 45 stopni").


#include <iostream>
using namespace std;

bool krokDoTylu(int stopnie){
cout << "Przesuwam sie do tylu o " << stopnie << " krokow." << endl;
return true;
}

bool krokDoPrzodu(int stopnie){
cout << "Przesuwam sie do przodu o " << stopnie << " krokow." << endl;
return true;
}

bool ObrotPrawy(int stopnie){
cout << "Obracam ramie w prawo o " << stopnie << " stopni." << endl;
return true;
}

bool ObrotLewy(int stopnie){
cout << "Obracam ramie w lewo o " << stopnie << " stopni." << endl;
return true;
}

bool wDol(int stopnie){
cout << "Opuszczam w dol o " << stopnie << " stopni." << endl;
return true;
}

bool doGory(int stopnie){
cout << "Podnosze do gory o " << stopnie << " stopni." << endl;
return true;
}

int main(){

short int ktory;
bool (*co[20])(int);
int stopnie[20];
int *wStopnie = stopnie;
cout << "-Robot Przemyslowy-";
for(int i = 0; i < 21; i++, wStopnie++){
cout << " 1. Krok do przodu";
cout << "\n 2. Krok do tylu";
cout << "\n 3. Obrot w prawo";
cout << "\n 4. Obrot w lewo";
cout << "\n 5. Opuszczenie";
cout << "\n 6. Podniesienie";
cout << "\n 7. Wykonaj\n";

cin >> ktory;
switch(ktory){
case 1:
co = &krokDoTylu;
cout << "Ile krokow do tylu?";
cin >> *wStopnie;
break;
case 2:
co = &krokDoPrzodu;
cout << "Ile krokow do przodu?";
cin >> *wStopnie;
break;
case 3:
co = &ObrotPrawy;
cout << "Ile stopni w prawo?";
cin >> *wStopnie;
break;
case 4:
co = &ObrotLewy;
cout << "Ile stopni w lewo?";
cin >> *wStopnie;
break;
case 5:
co = &wDol;
cout << "Ile stopni w dol?";
cin >> *wStopnie;
break;
case 6:
co = &doGory;
cout << "Ile stopni do gory?";
cin >> *wStopnie;
break;
case 7:
wStopnie = stopnie;
for(int j = 0; j < i; j++, wStopnie++){co[j](*wStopnie);}
break;
default:
cout << "Nie ma takiej opcji";
i--;
wStopnie--;
break;
}
cout << "Petla nr " << i << endl;
}
}


LXV. Napisz program, który na ekranie wypisze swoją nazwę, (nazwę swego pliku wykonywalnego) a w dodatku wszystkie parametry wysłane do niego z linii uruchamiającej ten program.


#include <iostream>
using namespace std;

int main(int argc, char * argv[])
{
cout << "Moja nazwa to: " << argv[0] << endl;
cout << "Moje pozostale parametry:\n";
for(int i = 1; i < argc; i++)
cout << "Parametr nr. " << i << " to: " << argv << endl;
}

 


9. Przeładowanie nazw funkcji

 


I. Kiedy mówimy o przeładowaniu? Czy potrafiłbyś wyjaśnić o przeładowanie czego czym tutaj chodzi?

Do przeładowania dochodzi wtedy, gdy więcej niż jedna funkcja mają tę samą nazwę oraz różne argumenty. Nazwę funkcji inną funkcją.


II. Wybierz poprawne dokończenia poniższego zdania:
Nazwa funkcji jest przeładowana, gdy istnieją dwie lub więcej definicji funkcji o tej samej nazwie…
a) w różnych zakresach ważności,
B) w tym samym zakresie ważności,
c) zakres tych nazw funkcji nie ma znaczenia,
d) funkcje te mają identyczną listę(typ i kolejność) argumentów,
e) funkcje te mają różną listę(typ i kolejność) argumentów,
f) lista argumentów tych funkcji nie ma znaczenia,
g) funkcje te mają ten sam typ rezultatu,
h) funkcje te mają różny typ rezultatu,
i) typ rezultatu nie ma znaczenia.

B), e), i)


III. Poniżej widzisz fragment kodu, gdzie w skrótowy sposób umieszczone są definicje 4 funkcji. Które z nich nie mogą się znaleźć się w tym samym zakresie ważności? (Bo wywołają błąd kompilacji)
typedef int cal;
enum akcja {stop, rusz, lewo, prawo};
enum dni {niedziela, poniedziałek, wtorek, środa, czwartek, piątek, sobota};
a) void funk(int liczba) {}
B) void funk(akcja a) {}
c) void funk(dni a){}
d) void funk(cal a){}

a) i d)


IV. W powyższym ćwiczeniu widzieliśmy definicje funkcji, Jak by zareagował kompilator gdyby były to nie definicje, ale deklaracje?

Tak samo.


V. W programie znajdują się definicje kilku poniższych funkcji. Które z nich mogą spowodować problemy i w jakiej sytuacji taki błąd wystąpi?
int deutz(int a) {return 1; }
double deutz(double d) {return 1.0; }
double deutz(char znak, int k = 6) { return 1.0; }
double deutz(int k, char znak = 'x'){ return 1.0;}

Pierwsza i ostatnia, gdyż w obu można użyć samego inta


VI. Załóżmy, że – na etapie linkowania – łączysz swój plik, napisany w C++, z innym plikiem napisanym w języku C. Z pliku C++ chcesz wywołać funkcję napisaną w języku C. Ma to być funkcja o nazwie rozruch wywoływana z dwoma argumentami - jeden typu int, drugi typu const char*, a zwracająca typ int.
Aby takie wywołanie w pliku C++ było w ogóle możliwe, musi tam znaleźć się deklaracja tej funkcji. Napisz deklarację tej funkcji w postaci, jaką ma mieć w pliku C++.

extern "C" int rozruch(int, const char*);


VII. Deklaracje wszystkich funkcji z pliku napisanym w języku C, są zebrane w odpowiednim pliku nagłówkowym o nazwie "dek1.h". Napisz jak można z tego pliku skorzystać w trakcie pisania pliku w języku C++.

extern "C" { #include "dek1.h" }


VIII. Która z wypowiedzi a), B), czy c) jest prawdziwa?
Jeśli w programie, w którym nazwa funkcji fun jest już przeładowana, otwieramy lokalny zakres, a w nim dodatkowo deklarujemy funkcje o tej samej nazwie to:
a) funkcja ta dołącza do zestawu funkcji przeładowujących tę nazwę
B) funkcja ta dołącza do zestawu funkcji przeładowujących tę nazwę(pod warunkiem, że takiej funkcji jeszcze nie ma, jeśli jest – następuje błąd kompilacji),
c) deklaracja ta unieważnia w tym zakresie przeładowanie tej nazwy fun – dokonując zasłonięcia jej.

c)


IX. Spośród poniższego zestawu funkcji przeładowujących nazwę F, wskaż te, które mogą być ze sobą w konflikcie
a) void F(char tab[ ]) { return;};
B) double F(int t[ ]) {return 1; };
c) char F(char *wsk) { return 1;};
d) char F(char tablica[4][5]) { return 1;};
e) char F(char (*tablica)[5]) { return 1;};
f) char F(char tablica[6][5]){ return 1;};
g) char F(char tablica[1][4][5]) { return 1;};

a), c), d), e), f)


X. Spośród poniższego zestawu funkcji przeładowujących nazwę G, wskaż te, które mogą być ze sobą w konflikcie
a) void G(int m);
B) void G(int *n);
c) void G(int &r);

a), c)


XI. Spośród poniższego zestawu funkcji przeładowujących nazwę rysuj, wskaż te, które mogą być ze sobą w konflikcie
a) void rysuj(int m);
B) void rysuj(int *m);
c) void rysuj(const int n);
d) void rysuj(const int *n);
e) void rysuj(volatile int k);
f) void rysuj(volatile int *k);

a), c), e)


XII. Ale serio: Nie powinieneś myśleć, że C++ polega na sztuce pisania deklaracji. To jest zupełny margines. Trzeba to wiedzieć, ale trzeba też wiedzieć, że nie to jest naprawdę ważne.
Po tych wszystkich zastrzeżeniach: koledzy ochotnicy od deklaracji "ekstremalnych" – oto wyzwanie dla was:
Napisz deklarację funkcji o nazwie fun, która przyjmuje dwa argumenty.
- Jeden z nich jest wskaźnikiem do funkcji wywoływanych z argumentem typu wskaźnik do char, a zwracających wskaźnik do double,
- Drugi argument jest wskaźnikiem do funkcji wywoływanych z dwoma argumentami typu int i typu double, a zwracających wartość typu double.
- Owa funkcja fun zwraca wskaźnik do funkcji wywoływanych z argumentem typu char* i zwracających rezultat typu char*.


char* (*fun( double*(*wsk)( char*), double(*wsk2)(int, double) ) (char*) )

 

 

10. Klasy - Ćwiczenia

 


I. Które z poniższych zdań są prawdziwe?
a) Klasa to obiekt.
B) Klasa to typ.
c) Składnikiem klasy może być obiekt typu double.
d) Składnikiem klasy może być funkcja.
e) Składnikiem klasy może być obiekt innej klasy.

B), c), d), e)


II. Wytłumacz na czym polega enkapsulacja.

Na zamknięciu(ukryciu) pewnych składowych we wnętrzu klasy i udostępnienie ich tylko metodom wewnętrznym.


III. Jaki zakres waźności mają funkcje składowe klasy?

Zakres ważności klasy.


IV. Czy można stworzyć w klasie funkcję składową o takiej samej nazwie, jak istniejąca funkcja globalna? Czy można jej dać takie same argumenty formalne? Jeśli tak zrobimy, to czy nastąpi:
a) błąd,
B) przeładowanie nazwy,
c) zasłonięcie nazwy.

Można, można oraz wystąpi zasłonięcie nazwy.


V. Czy w klasie mogą być dwie funkcje składowe o tej samej nazwie? Jeśli tak, to pod jakim warunkiem?

Tak, jeśli będą poprawnie przeładowane.


VI. Z jakich zakresów ważności dostępne są składniki klasy określone etykieta public?

Wszędzie.


VII. Z jakich zakresów ważności dostępne są składniki klasy określone etykieta private?

Tylko w klasie oraz jej funkcjach składowych.


VIII. Czy jeśli na początku definicji klasy nie postawimy etykiety określającej dostęp, to jaki dostęp, przez domniemanie, mają postawione tam skłądniki: public, protected czy private?

Private.


IX. Czy w danej klasie funkcja składowa public może wywołać funkcję składową private?

Tak.


X. Czy, jeśli funkcja składowa klasy, ma ciało zdefiniowane poza definicją klasy - to ma dostęp do składników private?

Tak.


XI. Jaka jest istotna różnica między definiowaniem funkcji składowej wewnątrz definicji klasy, a definiowaniem tej samej funkcji składowej poza ciałem klasy?

Funkcje wewnątrz są z automatu definiowane inline, a na zewnątrz niekoniecznie.


XII. Co oznacza używanie przez niektórych programistów określenie "metoda danej klasy"?

Funkcja składowa danej klasy.


XIII. Jeśli na rzecz obiektu A wywołamy zwykłą funkcję składową z jego klasy, na co pokazuje w tej funkcji składowej wskaźnik this? Jakiego jest on wtedy typu?

Wskaźnik this pokazuje na obiekt A, jest typu takiego jakim jest obiekt A.


XIV. W klasie wolno zdefiniować składnik-daną o takiej samej nazwie, jak obiekt globalny o nazwie temperatura. Jak w funkcji składowej tej klasy można odnieść się do takiego składnika globalnego?

Operatorem ::


XV. W funkcji składowej klasy A stworzyliśmy jakiś zakres lokalny(np. blok if), a w nim jest definicja obiektu o nazwie (nnn) identycznej z nazwą składnika-danej (nnn) tej klasy, i równocześnie identyczna z nazwą(nnn) obiektu globalnego.
a) Czy mamy tu do czynienia z zasłanianiem nazwy, czy z przeładowaniem nazwy?
B) Czy można w tym zakresie lokalnym odnieść się do tego obiektu globalnego? Jeśli tak, to jak?
c) Czy można w tym zakresie lokalnym odnieść się do tego składnika-danej? Jeśli tak, to jak?
d) Czy można w tym zakresie lokalnym odnieść się do tego lokalnego obiektu? Jeśli tak to jak?

a) - zasłonięciem B) można - operatorem :: c) można - A::nnn. d) Tak, normalnie: nnn


XVI. Czy nazwa obiektu może zasłonić nazwę funkcji?

Tak.


XVII. Czy nazwa funkcji moze zasłonić nazwę obiektu?

Tak.


XVIII. Czy w klasie A może nastąpić przeładowanie nazwy funkcji składowej fff, która już zasłania nawę funkcji globalnej fff?
Jeśli w zakresie tej klasy wywołujemy funkcję o nazwie fff, a zestaw argumentów wywołania nie pasuje(dokładnie) do deklaracji składowych funkcji fff, natomiast pasuje do deklaracji globalnej funkcji fff - co wtedy zrobi komilator?

Tak. Błąd, nie weźmie pod uwage globalnej..


XIX. Przypomnij, przed czym strzeże nas tzw. strażnik nagłówka?

Przed wstawieniem tego samego pliku nagłówkowego drugi raz.


XX. Poznaliśmy zasadę "Każda klasa w osobnym pliku", ale oczywiście należałoby ją raczej wymienić na taką "Każda klasa w osobnych dwóch plikach". Na czym to polega?

W jednym pliku klasy jej definicja i deklarację funkcji składowych, a w drugim pliku definicje tych funkcji.


XXI. Mamy klasę o nazwie TTT. Jednym z jej składników danych jest 8000-elementowa tablica obiektów typu int. Ma ona nazwę t1. Dokończ poprawnie następujące zdanie.
Gdy obiekt obj klasy TTT, wysyłamy przez wartość do jakiejś funkcji to:
a) - otrzymuje ona wskaźnik do tablicy t1 obiektu obj.
B) - otrzymuje ona oryginał tablicy t1 obiektu obj.
c) - otrzymuje ona kopię tablicy t1 obiektu obj.

c)


XXII. Mamy klasę M. Jaki jest typ rezultatu jej funkcji składowej zwanej konstruktorem tej klasy? Jaka jest pełna nazwa tego konstruktora?

Nic nie zwraca. Jego pełna nazwa: M::M


XXIII. Jaka jest pełna nazwa destruktora klasy M? Jaki jest typ jej rezultatu?

~M::M, nic nie zwraca.


XXIV. Czy w klasie M można dokonać przeładowania konstruktora?

Tak.


XXV. Czy w klasie M można dokonać przeładowania destruktora?

Nie.


XXVI. Mamy klasę K, której publicznym składnikiem statycznym jest obiekt typu bool o nazwie flaga. W funkcji main zdefiniowane są tryz obiekty tej klasy K. Mają nazwy x1, x2, x3.
Jeśli obiekt x1 wpisał sobie do tego składnika flaga wartość true...
a) jak o tym mogą się dowiedzieć obiekty x2 i x3?
B) jak można się dowiedzieć tego z zakresu funkcji main?(Podaj tu 4 możliwe sposoby)

a) poprzed składnik statyczny flaga B) - za pomocą nazwy klasy i operatora zakresu, operatorem ".", wskaźnikiem do obiektów danej klasy, przez skłądnik statyczny.


XXVII. Czy składnik statyczny prywatyn może mieć przy swojej definicji(leżącej poza ciałem klasy) - wyrażenie inicjalizujące go?

Tak.


XXVIII. Słowo w definicji składnika statycznego klasy K, leżącego poza ciałem klasy K, nie występuje słowo static - skąd kompilator ma wiedzieć, że jest to składnik statyczny?

Słowo static znajduje się w deklaracji zmiennej, w ciele klasy.


XXIX. Klasa K ma składnik nie-statyczny typu int o nazwie sn oraz składnik statyczny typu int o nazwie ss.
a) Jaka jest pełna nazwa typu składnika sn?
B) Jaka jest pełna nazwa typu składnika ss?

a) K::int B) KK::static int


XXX. Założmy, że mamy klasę K, a jeszcze nie zdefiniowaliśmy ani jednego obiektu tej klasy.
Wybierz poprawne dokończenia następującego zdania.
W statycznej funkcji składowej klasy K możemy...
a) - pracować ze statycznymi publicznymi składnikami tej klasy
B) - pracować ze statycznymi prywatnymi składnikami tej klasy
c) - pracować z nie-statycznymi publicznymi składnikami tej klasy
d) - pracować z nie-statycznymi prywatnymi składnikami tej klasy

a), B)


XXXI. W klasie K jest statyczna funkcja składowa o nazwie fun.
Jak ją wywołać, jeśli jeszcze nie ma ani jednego obiektu tej klasy?

K::fun()


XXXII. W klasie K jest statyczna funkcja składowa o nazwie fun. Jaki jest w niej typ wskaźnika this?

Nie ma tam wskaźnika this.


XXXIII. Czy statyczną funkcję składową można wywołać na rzecz jakiegoś obiektu tej klasy?

Tak.


XXXIV. Deklaracja funkcji składowej w klasie K oznajmnia, że jest to funkcja z przydomkiem const.
a) W którym miejscu deklaracji umieszcza się ten specyfikator?
B) Jeśli funkcja const ma ciało zdefiniowane poza definicją klasy, czy powtarza się tam specyfikator const? Jeśli tak, to gdzie? Jeśli nie to dlaczego?

a) na końcu, po nawiasach z argumentami przed średnikiem. B) Tak samo jak przy deklaracji.


XXXV. Czy mając stały obiekt klasy K można dla niego wywołać funkcję składową const?

Tak.


XXXVI. Czy mając nie-stały obiekt klasy K można dla niego wywołać funkcję składową const?

Tak.


XXXVII. Czy dla stałego obiektu tej klasy można wywołać funkcję nie-const?

Nie.


XXXVIII. Czy dla nie-stałego obiektu klasy K można wywołać funkcję składową nie-const?

Tak.


XXXIX. Z tekstu dla dociekliwych. Mamy klasę K. w niej są funkcje z przydomkiem const i volatile
a) Jaki jest typ wskaźnika this w funkcji składowej const?
B) Jaki jest typ wskaźnika this w funkcji składowej volatile?
c) Jaki jest typ wskaźnika this w funkcji składowej const volatile?

a) const K * B) volatile K * c) const volatile K *


XL. Czy konstruktor, który nie ma przydomka const może pracować na rzecz stałego obiektu swojej klasy?

Tak.


XLI. Czy przydomek mutable może być zastosowany także do obiektu globalnego?

Nie.


XLII. Jakie działanie ma przydomek mutable w obiektach klasy K, które nie są stworzone jakie stałe?

Nic nie robi.


XLIII. W klasie K, jeden ze składników-danych ma przydomek mutable. Jeśli stworzymy stały obiekt tej klasy, na co pozwala ten przydomek mutable?

Na modyfikację tego składnika klasy w funkcjach typu const.


 

11. Std::string – Ćwiczenia

 


I. W danym programie C++ włączyłeś nagłówek
#include <string>
a później zamieściłeś definicję
string n;
W trakcie kompilacji kompilator wskazuje na tę linie definicji mówiąc, że nie zna nazwy string. Co należy zrobić? Podaj co najmniej dwa rozwiązania

using namespace std bądź std::string


II. Czy plik nagłówkowy <string> to nowsza wersja pliku <string.h>? Czy można je stosować wymiennie? Dlaczego?

Tak, string.h jest starszy i nie należy ich stosować zamiennie, starsza wersja zawiera całkowicie inną treść


III. Co to jest C-string? W jakim obiekcie się go przechowuje?

Jest to ciąg znaków zakończony nullem. Nie jest sam w sobie obiektem, jest miejscem w pamięci, bądź tablicą znaków.


IV. Które z poniższych operatorów NIE można zastosować wobec klasy string?
+, +=, ==, !=, <, >, >=, <=, !, /, ^, &&, [], <<, >>, *

/, ^, &&


V. Które z poniższych definicji są poprawne?
string a("123");
string b('X');
string c = "XYZ";

string b('X') jest niepoprawna.


VI. Czy jeśli tekst w obiekcie klasy string przesyłamy do funkcji
void f(string);
to czy pracuje ona na oryginale?
Jeśli TAK, to co zmienić w deklaracji, by zabezpieczyć się przed zniszczeniem treści stringu przez funkcję?
Jeśli NIE, to co zmienić w deklaracji, by funkcja mogła dokonywać zmian w oryginalnym stringu?

Nie, należałoby przesuwać argument referencję bądź wskaźnik


VII. Użytkownik programu powinien z klawiatury wpisać do programu wyraz. Aby to było możliwe w programie nalezy przygotować na ten cel obiekt klasy string. Co zrobić jeśli spodziewamy się, że wyraz będzie długi?(Nie więcej jednak niż 50 znaków).

Nic nie trzeba robić.


VIII. W jakimś obiekcie znajduje się znak. Napisz definicję obiektu klasy string, który od razu będzie inicjalizowany będzie zawartością tego obiektu char.

string b(&a)


IX. Które z poniższych definicji są niepoprawne?
int m = 4;
int p = 6;
size_type a = m;
size_type b = m + p;
size_type c = m - p;
size_type d = p - m;
size_type e = m * p;

size_type c = m - p


X. Co oznaczają rezultaty funkcji size i funkcji length. Jaka jest między nimi różnica?

Mówią z ilu znaków składa się dany string, nie ma pomiędzy nimi różnicy.


XI. Jeśli wywołana na rzecz jakiegoś obiektu klasy string funkcja length zwróciłą wartość 25, to jaką wartość zwróciłaby funkcja empty?

Zwróci false.


XII. W danym obiekcie klasy string jest tekst "Biosynteza bialka". Jeśli na rzecz tego obiektu wywołamy funkcje max_size - jak należy rozumieć zwracaną przez nią wartość?

OBECNA maxymalna wartość, gdyż ona może się zmieniać.


XIII. Jaka jest różnica między funkcjami max_size i capacity. Jak należy rozumieć zwracane przez nich wartości.

max_size mówi jaki długi string moglibyśmy teraz przechować w tym stringu, a capacity jak duży obszar zarezerwował sobie dany string.


XIV. Do końca danego obiektu klasy string zamierzamy dopisać właśnie operatorem += dopisać 500 znaków. Czy należy wcześniej zarezerwować na nie miejsce funkcją reserve?

Nic nie trzeba robić.


XV. Wyjaśnij, jaka jest różnica między działaniem funkcji reserve, a funkcji resize. Co może powiększyć każda z nich?

reserve powiększa "pojemnik", ewentualnie zmniejsza, a resize zmienia długość stringu.


XVI. Co zrobić jeśli w Twojej realizacji biblioteki standardowej nie ma w klasie string funkcji składowej clear. Jak najprościej można wykonać tę samą operację?(Podaj co najmniej dwa sposoby).

nazwa.erase();
nazwa = "";


XVII. Mamy taki fragment programu.
string star("co i jak");
char znak;
znak = star[25000];
znak = star.at(25000);
cout << "dlugosc stringu " << star.length();
Jak zachowa się program w obu przypadkach przypisywania do obiektu znak?

W pierwszym postąpi tak jak mu każemu, przy drugim wyrzuci błąd.


XVIII. Jaką funkcją można wydobyć z danego obiektu klasy string fragment zaczynający się od znaku N i mający długóść Z znaków?

nazwa.substring(N, Z)


XIX. Mamy jakiś obiekt klasy string, w którym jest tekst zawierający kilkakrotnie znak '.'. Jaką funkcją można najprościej zlokalizować wystąpienie tej kropki?

rfind


XX. Jeśli funkcje z rodziny find odpowiadają wartością string::npos - co to oznacza?

To co chcieliśmy znaleźć nie zostało odnalezione.


XXI. Jest kilka funkcji składowych klasy string, których z jednym argumentów jest liczba znaków, na których mają wykonać daną pracę. Jeśli jako ten argument wyślemy im wartość string::npos - co to oznacza?

Mają wykonać pracę do końca stringu.


XXII. Jeśli funkcjom składowym z rodziny find wskazujemy gdzieś w środku stringu miejse skąd należy poszukiwanie - w którą stronę zaczyna się poszukiwanie w przypadku poniższych funkcji?
a) find_first_of
B) find_first_not_of
c) find_last_of
d) find_last_not_of

a), B) - w stronę końca c), d) - od końca do początku.


XXIII. W funkcjach składowych klasy string często argumentami są:
- pozycja określająca numer znaku, od którego funkcja ma zacząć pracę
- liczba znaków, które mają zostać poddane operacji.
Możliwe, że programista korzystający z tych funkcji poda niewłaściwe wartości argumentów. To znaczy albo poda niewłaściwy numer pozycji(gdzieś daleko poza końcem stringu), lub poda za dużą liczbę znaków(string jest krótszy).
Jak w tych dwóch przypadkach zachowa się funkcja? Jaka praca zostanie wykonana(lub nie). Jak wpłynie to na dalsze działanie programu?

Niewłaściwa pozycja - wyjątek out_of_range Za duża ilość znaków - nic się nie stanie.


XXIV. Mamy string składający się z 20 znaków. Jeśli teraz za pomocą funkcji insert pięc znaków począwszy od znaku piątego, to co się stanie z dotychczasowym znakiem piątym, szóstym i siódmym?

Zostaną przesunięte dalej.


XXV. Mamy string składający się z 20 znaków. Jeśli teraz za pomocą funkcji replace pięć nowych znaków w miejsce znaku piątego i szóstego - to co sie stanie z dotychczasowym znakiem piątym, szóstym i siódmym?

5,6 zostanie zniszczony - reszta przesunięta do przodu.


XXVI. Mamy wywołać jakąś funkcję, której argumentem ma być nazwa pliku w postaci C-stringu. Tymczasem w naszym programie nazwa ta jest treścią obiektu klasy string. Co robić?

Użyć na nim funkcję składową .c_str()


XXVII. Funkcje składowe data i c_str mają ten sam typ rezultatu const char* i obie pozwalają poznać bieżącą zawrtość obiektu klasy string. Jaka jest między nimi zasadnicza różnica? Dlaczego w typie rezultatu jest przydomek const?

data - zwraca adres stringu - żeby nie było można go zmieniać, c_str kopiuje string na c-string - żeby nie można było go zmieniać.


XVIII. Dla dociekliwych: Wyjaśnij, dlaczego z rezultatów funkcji składowych c_str i data należy skorzystać "od razu", (czyli przed nastepną ewentualną modyfikacją stringu - np. operatorami +=, =, czy funkcjami insert, replace).

Gdy zaczniemy na nich "kombinować", string może się zmienić i c-string będzie "nieaktualny", data - adres może ulec zmianie


XXIX. Klasa string dostarcza nam funkcji składowej compare oraz operatorów >, <, <=, >=, !=, == do porównywania reści stringów. Które z nich przy tych porównaniach są czułe na wielkie i małe litery, a które nie?

Wszystkie są czułe.


XXX. Funkcja compare dokonuje porównania treści obiektu(na rzecz którego została wywołana) z innym stringiem. Jako rezultat swej pracy może swrócić jedną z trzech wartości. Jakie to wartości i jak należy rozumieć każdą z tych odpowiedzi?


-1 - string na którym wywołaliśmy funkcję stoi alfabetycznie przed drugim stringiem
0 - string na którym wywołaliśmy funkcję stoi alfabetycznie na tym samym miejscu
1 - string na którym wywołaliśmy funkcję stoi alfabetycznie pod drugim stringu


XXXI. Jaki jest typ rezultatu porównania dwóch stringów za pomocą operatorów >, <, <=, >=, !=, ==
Co oznacza każda z możliwych wartości?


> – string po lewej jest większy niż string po prawej
< – string po prawej jest większy niż string po lewej
>= – string po lewej jest większy lub równy stringowi po prawej
<= – string po lewej jest mniejszy lub równy stringowi po prawej
== – oba stringi są równe
!= – stringi są nierówne


XXXII. Czy za pomocą operatorów >, <, <=, >=, !=, == można dokonać takiego porównania, w którym po lewej stronie operatora stoi C-string, a po prawej obiekt klasy string? Jakie są możliwe, a jakie niemożliwe kombinacje przy takich porównaniach?

Jest to niemożliwe tylko C-string - c-string


XXXIII. Napisz definicję funkcji, która będzie można wywołać z dwoma argumentami klasy string, a która dokona ich porównania wg. porządku alfabetycznego - ale w przeciwieństwie do funkcji compare - tutaj porównanie ma być nieczułe na wielkość liter.(To znaczy wielka litera 'A' oraz mała litera 'a' - według takiego porównania są według porządku alfabetycznego identyczne). Funkcja powinna zwracać o znaczeniu podobnym do rezultatu jak funkcji compare.

 

#include <iostream>#include <string>#include <cctype>using namespace std;int comparing( string tekst1, string tekst2){    for( int i = 0; i < tekst1.length(); i++){    tekst1[i] = tolower(tekst1[i]);    }    for( int i = 0; i < tekst2.length(); i++){    tekst2[i] = tolower(tekst2[i]);    }    if(tekst1 < tekst2) return -1;    if(tekst1 > tekst2) return 1;    else if(tekst1 == tekst2) return 0;} int main(){    string napis1("A");    string napis2("a");    int porownujaca = comparing(napis1, napis2);    if(porownujaca == -1)    {        cout << napis1 << " jest wczesniej niz " << napis2;    }    if(porownujaca == 1)    {        cout << napis1 << " jest pozniej niz " << napis2;    }    if(porownujaca == 0)    {        cout << napis1 << " jest na tym samym miejscu co " << napis2;    }} 

 


XXXIV. Jaką funkcją możemy treść obiektu klasy string skopiować do tablicy char? Jeśli za pomocą tej funkcji do pustej tablicy char skopiujemy całą zawartość obiektu klasy string, to czy w rezultacie powstanie C-string będący kopią zawartości obiektu string?

Funkcją copy, nie, bo nie funkcja nie dodaje zera na koniec tego co skopiowała.


XXXV. Co robi funkcja assign i czy można ją najczęściej zastąpić?

Przypisaniem czegoś do stringu, można zastąpić operatorem =.


XXXVI. Co się dzieje z dotychczasową treścią obiektu klasy string w przypadku wywołania funkcji składowej assign, a co w przypadku wywołania funkcji składowej append?

assign - przypisuje nową wartość do c-stringu, ale poprzednia zostaja skasowana, append - "zwiększa" string o jakąś wartość, jak operator +=.


XXXVII. Czym można najczęściej zastąpić wywołanie funkcji składowej append?

Operatorem +=.


XXXVIII. Nazwę funkcji getline można przetłumaczyć jako "weź linię"(tekstu). W jaki sposób wobec tego można wczytać za jednym razem kilkanaście linii tekstu?

Ustalamy ogranicznik, po jakim się kończy wczytywanie tekstu.


XXXIX. Wytłumacz, co się dzieje w przypadku pracy funkcji getline z tak zwanym ogranicznikiem. Po co potrzebny jest ten znak? Co funkcja getline robi napotkawszy ten znak w strumieniu danych? Co robi z nim ostatecznie?

Jest on po to, aby funkcja wiedziała kiedy ma skończyć pobierać tekst, ostatecznie jest usuwany.


XL. Czy funkcja getline może wczytać białe znaki poprzedzające pierwszy wyraz spodziewanego długiego tekstu?

Tak, jeśli są zostawione przez strumień cin.


XLI. Czy biały znak może być ogranicznikiem?(W wywołaniu funkcji getline).

Tak.


XLII. Operator wczytywania >> i funkcja getline inaczej postepują z ogranicznikiem wczytywanego tekstu. Na czym polega różnica i jakie to może mieć dla nas niespodziewane konsekwencje? Jak można temu zaradzić?

cin ignoruje białe znaki, ale je zostawia w strumieniu, a jak po tym użyjemy getline to te białe znaki w strumieniu będą i mogą narobić kłopotów, użyć cin.ignore bądź użyć dwa razy getline.


XLIII. Funkcja getline nie jest funkcją składową klasy string. Czy jeśli za pomocą tej funkcji zamierzamy wczytać do obiektu klasy string dłuższy tekst - czy musimy dla tego obiektu zarezerwować miejsce?

Nie.


XLIV. Napisz funkcję, która otrzymawszy(jako argument)obiekt klasy string pokaże na ekranie kolejno wszystkie jego znaki. Każdy znak powinien być ujęty w nawiasy kwadratowe. Przykładowo: string o treści "Gen" powinien być pokazany na ekranie jako [G][e][n].

 

#include <iostream>#include <string>using namespace std;int pokazywacz(string napis){    for(int i = 0; i < napis.length() ; i++)        cout << "[" << napis[i] << "]";}int main(){string napis1 = "Andrzej";pokazywacz(napis1);}

 


XLV. Napisz funkcję, która z nazwy pliku przysłanej jako argument klasy string usunie ewentualne rozszerzenie i rezultat zwróci jako obiekt klasy string. Przykładowo: funkcja ta otrzymawszy nazwę "rezerwacje_luty.dane" jak rezultat zwróci nazwę "rezerwacje_luty". Uwaga: Rozszerzenie może mieć dowolną długosć.

 

string usuwacz(string napis){    int pozycja = napis.find('.');    napis.erase(pozycja);    return napis;}

 


XLVI. Napisz funkcję, która poleci uzytkownikowi wprowadzić(z klawiatury) nazwę jakiegoś pliku tekstowego. Nazwa ta ma zostać zapisana w obiekcie klasy string. Funkcja ta ma sprawdzić, czy w nazwie użytkownik podał rozszerzenie ".txt". Jeśli nie ma żadnego rozszerzenia, w funkcjimasz dodać rozszerzenie ".txt". Jeśli jest rozszerzenie, ale inne niż ".txt", zamień na takie. Funkcja(jako rezultat) ma zwrócić obiekt klasy string zawierający tak zmodyfikowaną nazwę pliku.

 

string rozszerzacz(){  string nazwa;  cin >> nazwa;    const string rozszerzenie(".txt");                 if(nazwa.find('.') == string::npos)                {                        nazwa += rozszerzenie;                }                else                {                        nazwa.erase( (nazwa.find('.')) );                        nazwa += rozszerzenie;                }        return nazwa;} 

 


XLVII. Napisz funkcję, która w stringu(przysyłanym jako argument) zamieni w taki sposób, że znaki parzyste będą napisane literami wielkimi, a nieparzyste - małymi. Wynik pracy zapisany w obiekcie klasy string ma być rezultatem zwracanym przez tę funkcję.

 

string parzyste(string tekst){    for(int i = 0; i < tekst.length(); i++){         if(i == 0 || !(i%2)){            tekst[i] = toupper(tekst[i]);        }        else tekst[i] = tolower(tekst[i]);    }    return tekst;}

 


XLVIII. W pewnym międzynarodowym urządzeniu badawczym jest piętnaście identycznych modułów. Ich nazwy składają się z trzonu np. "Cluster_", za którym następuje jednoliterowy symbol. Oto stosowane litery:
ABCDEFGJKLMNPQR
Na pierwszy rzut oka wydaje się, że są to kolejne litery alfaberu, ale są tu wyjątki. Nie ma litery "H", bo Włosi i Francuzi mają trudności z ich wymawianiem. Nie ma litery "I", bo mogłaby nastąpić pomyłka z jedynką. Nie ma litery 'O', bo za bardzo przypomina zero.
Napisz funkcję, która pełną nazwę modułu przysłaną do niej jako argument - (na przykład "Cluster_M") rozpozna w taki sposób, że jako rezultat (typu int) zwróci numer modułu. Ów numer - to jakby numer litery, według porządku, w jakim widzisz je napisane powyżej.(Numerujemy od zera). Na przykład nazwa "Cluster_M" - określa moduł numer 10.

 

int rozpoznanie(string nazwa){  string::size_type pozycja;    string symbol = "ABCDEFGJKLMNPQR";    for(pozycja=0; pozycja <= 15; pozycja++){       if(nazwa.find(symbol.at(pozycja), 1) != string::npos)break;                }                return pozycja;

 


IL. Napisz funkcję, wywoływaną z jednym argumentem klasy string, a zwracającą jako rezultat obiekt typu string. Funkcja powinna zanalizować przyslaną do niej nazwę pliku.
- Jeśli nazwa ta ma rozszerzenie inne niż ".poly", to funkcja powinna zwrócić string pusty.
- Jeśli nazwa ma rozszerzenie ".poly", to należy w tej nazwie znaleźć ostatnie wystąpienie wyrazu "_polygon_".(Jeśli nie ma - funkcja ma zwrócić string pusty).
- Jeśli zaś "_polygon_" w tej nazwie jest, to funkcja powinna jako rezultat zwrócić substring zaczynający się bezpośrednio za tekstem "_polygon_" i ciągnący się do kropki oznaczającej początek rozszerzenia.
Przykład: jeśli przysłana(jako argument) nazwa pliku brzmiałaby:
"matrix_zet_vs_aoq_polygon_cr54.poly",
to funkcja powinna zwrócić jako rezultat
"cr54"

 

string analizaNazwyPliku(string nazwaPliku){ if( nazwaPliku.find(".poly") != string::npos)    if(nazwaPliku.find_last_of("_polygon_") == string::npos){        nazwaPliku.clear();        return nazwaPliku;    }    if(nazwaPliku.find_last_of("_polygon_")!= string::npos){        int pozycja = nazwaPliku.find_last_of("_") + 1;        int pozycja2 = nazwaPliku.find('.');        return nazwaPliku.substr(pozycja, pozycja2 - pozycja);    } }

 


L. Napisz funkcję, do której można wysłać obiekt klasy string zawierający długi, wielolinijkowy tekst. Funkcja ta powinna ten tekst wydrukować na ekranie - rozpoczynając każdą linijkę tekstem opisującym jej numer. To znaczy, jeśli byśmy wysłali następujący tekst:
Narodowa Galeria,
wielka sztuka na serio
owionela nas chlodem swych sal
to funkcja wydrukuje na ekranie
Linia 1: Narodowa Galeria,
Linia 2: wielka sztuka na serio
Linia 3: owionela nas chlodem swych sal

 

void wypisz(string a){        cout << "Linia 1: ";         for(int i = 0, k = 2; i < a.length(); i++)        {                               cout << a[i];                 if(a[i] == '\n')                 {                        cout << "Linia " << k << ": ";                        k++;                }        }        cout << endl;}

 


LI. Obiekty klasy string mogą być zgrupowane w tablice. Na przykłąd może być tablica przystanków tramwaju lub metra. Nazwy przystanków oczywiście mogą być wielowyrazowe.
Napisz funkcję o nazwie przystanek, w której składnikiem statycznym będzie tablica stringów z kolejnymi przystankami danej linii tramwajowej. Funkcja wywołana ma być z argumentem oznaczającym numer najbliższego przystanku. Funkcja ma wówczas zwróccić jako rezultat stringu opisujący następny przystanek. To znaczy na przykład taki string: "Nastepny przystanek: Teatr Bagatela."

 

string nastepnyPrzystanek(int numerPrzystanku){static string przystanki[] = {"A", "B", "C", "D", "E", "F"};string nextPrzystanek = "Nastepny przystanek: ";if(numerPrzystanku != 5) nextPrzystanek += przystanki[numerPrzystanku];else nextPrzystanek += "Wracamy do bazy!";return nextPrzystanek;}

 


LII. Dla bardziej dociekliwych. Napisz funkcję która wywoływana będzie z jednym argumentem będącym liczbą z zakresu 0 - 99. Rezultatem zwracanym przez funkcję ma być string opisujący słownie tę liczbę - czy jest parzysta czy nie parzysta.
Przykładowo jeśli wywołano ją by dla liczby 55 - powinna wydrukować string o treści "Liczba 55 jest nieparzysta".
Wskazówka - parzystość łatwo sprawdza się operatorem reszty z dzielenia. Natomiast istotą tego zadania jest zamiana liczby 55 na ciąg znaków "55".

 

string sprParzystosci(int liczba){string cyfry = "0123456789";string zwrot = "Liczba ";int dziesiatki = liczba / 10;int jednostki = liczba % 10; if(!(liczba % 2)){    if(liczba > 9)zwrot += cyfry[dziesiatki];    zwrot += cyfry[jednostki];    zwrot += " jest parzysta";}else {    if(liczba > 9)zwrot += cyfry[dziesiatki];    zwrot += cyfry[jednostki];    zwrot += " nie jest parzysta";}return zwrot;}

 


LIII. Napisz funkcję, która otrzymawszy jako argument liczbę całkowitą z przedziału [-9999 +9999] w rezultacie zwróci string ze słownym wyrażeniem tej liczby.
To znaczy: gdy wyślemy do niej liczbę 729, w rezultacie otrzymamy string "siedemset dwiadziescia dziewiec".

 

string wypisLiczby(int liczba){ string tysiace[] = {"", "tysiac", "dwa tysiace", "trzy tysiace", "cztery tysiace", "piec tysiecy", "szesc tysiecy", "siedem tysiecy", "osiem tysiecy", "dziewiec tysiecy"};string setki[] = {"", "sto", "dwiescie", "trzysta", "czterysta", "piecset", "szescset", "siedemset", "osiemset", "dziewiecset"};string dziesiatki[] = {"", "dziesiec", "dwadziescia", "trzydziesci", "czterdziesci", "piecdziesiat", "szescdziesiat", "siedemdziesiat", "osiemdziesiat", "dziewiedziesiat"};string jednostki[] = {"", "jeden", "dwa", "trzy", "cztery", "piec", "szesc", "siedem", "osiem", "dziewiec"};string odDziesiatki[] ={"", "jedenascie", "dwanascie", "trzynascie", "czternascie", "pietnascie", "szesnascie", "siedemnascie", "osiemnascie", "dziewietnascie"};string zwrotny;int jedno, dziesi, set, tys, kopia;kopia = liczba;if(liczba < 0){ liczba = -liczba; }if(liczba < 10 && liczba >= 0){    if(liczba == 0) zwrotny += "zero";    else zwrotny += jednostki[liczba];    cout << liczba<< " ";}if( (liczba >= 10 && liczba < 20)){    if(liczba == 10){    zwrotny += dziesiatki[1];    cout << liczba << " ";    }    else{    dziesi = liczba - 10;    zwrotny += odDziesiatki[dziesi];    cout << liczba << " ";    } }if(liczba < 100 && liczba >= 20){jedno = liczba % 10;dziesi = (liczba - jedno) / 10;cout << dziesi << jedno << " ";zwrotny = dziesiatki[dziesi] + " ";zwrotny += jednostki[jedno]; }if(liczba >= 100 && liczba < 1000){set = liczba / 100;dziesi = (liczba % 100) / 10;jedno = liczba - ((liczba / 10 )* 10);cout << set << dziesi << jedno << " ";zwrotny = setki[set] + " " + dziesiatki[dziesi] + " " + jednostki[jedno];} if(liczba >= 1000 && liczba < 10000){     tys = liczba / 1000;    set = (liczba % 1000) / 100;    dziesi = ((liczba / 10) % 1000) % 10;    jedno = ((liczba % 1000) % 100) % 10;    cout << tys << set << dziesi << jedno << " ";    zwrotny = tysiace[tys] + " " + setki[set] + " " + dziesiatki[dziesi] + " " + jednostki[jedno];}if(kopia < 0) zwrotny.insert(0, "minus ");int pozycja;if(dziesi == 1) {    pozycja = zwrotny.find("dziesiec");    zwrotny.replace(pozycja, string::npos, odDziesiatki[jedno]);}return zwrotny;} 

 


Napisz funkcję
string litera_alfabetu(int );
która otrzymawszy jako argument litery - odpowie stringiem wyjaśniającym, która to jest litera w alfabecie angielskim. Przykładowo: jeśli funkcję tę funkcję wywołamy z wartością 6, wówczas odpowie ona takim tekstem: "W alfabecie litera nr 6 to litera F".

 

string litera_alfabetu(int nrLitery){string alfabet = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";string zwrot = "Litera o tym numerze to: ";zwrot += alfabet.at(nrLitery);cout << zwrot;return zwrot;}

 


LV. Napisz krótki program, który wywoływany będzie z dwoma argumentami. Pierwszy argument będziemy okreslać na przykład rodzaj miejsca, skąd program będzie czytał dane. Mogą być takie wartości tego parametru
-serwer
-plik
-strumien
Drugim argumentem będzie jakaś nazwa. Na przykłąd nazwa serwera, liku itp. Drugi argument nie ma w tym ćwiczeniu specjalnego znaczenia.
Jak pamiętamy, jeśli wywołujesz program nie tylko pisząc jego nazwę, ale dodatkowo podając argumenty - to przychodzą one do programu w postaci C-stringów.
Przepisz je najpierw do obiektów klasy string, następnie rozpoznaj jakiego trybu pracy żąda użytkownik. Zrobisz to analizując cztery pierwsze znaki pierwszego argumentu. Tylko cztery znaki, bo to wystarczy do rozpoznania trybu.
Program powinien przyjąć i ocenić te argumenty, po czym wypisać na ekranie tekst wyjaśniający.[
Na przykład, jeśli wywołany został w jeden z poniższych sposobów:
program -ser lxg1013
program -plik europium152_cal.lmd
program -stru cin
Powinien na ekranie napisać odpowiednio:
"Dane przychodzic beda z serwera lxg1013"
"Dane przychodzic beda z pliku europium152_cal.lmd"
"Dane przychodzic beda ze strumienia cin"

 

#include <iostream>#include <string>using namespace std; int main(int argc, char * argv[]){string miejsce = argv[1];string nazwa = argv[2]; string opis = "Dane beda przychodzic z "; if( miejsce.find("serw") != string::npos) opis += "serwera ";else if(miejsce.find("plik") != string::npos) opis += "pliku ";else if(miejsce.find("stru") != string::npos) opis += "e strumienia "; opis += nazwa;cout << opis << endl;}

 


 

12. Struktury, unie i pola bitowe

 

 

 

I. Czym się różni struktura od klasy?


W klasie domniemanie składniki są prywatne, a w strukturze publiczne.



II. Można powiedzieć, że w klasie czy strukturze poszczególne składniki umieszczane są obok siebie. A jak umieszczane są w unii?


Umieszczane są na sobie.



III. Dokończ poprawnie następujące stwierdzenie. Rozmiar unii wynika:
a) - z ilości jej składników,
B) - z wielkości największego składnika,
c) - z ilości składników publicznych.


B) - z wielkości największego składnika.



IV. Mamy unię, której składnikiem jest obiekt typu char i obiekt typu double. Jeśli w obiekcie tej unii przechowywana jest właśnie wartość typu char, to czy można wówczas włożyć do tego obiektu wartość typu double?


Tak.



V. Tworzymy obiekt jakiejś unii, a chielibyśmy od razu nadać mu wartość(inicjalizacja). Jakiego typu musi być to wartość?


Wartość musi być typu pierwszego od góry obiektu unii.



VI. Jaka jest składnia wyrażenia odnoszącego się do składnika unii - w przypadku unii zwykłej, a jaka w przypadku unii anonimowej?


Zwykła - nazwaunii.nazwaobiektu lub wskaznik_na_unie->nazwaobiektu
Anonimowa - nazwaobiektu



VII. Czy w przypadku unii anonimowej są jakieś ograniczenia co do typu, lub co do nazwy składników? Jeśli tak, to jakie?


W danym zakresie lokalnym nie może być takich samych nazw obiektów, gdyż nastąpiła by redefinicja.



VIII. Jak stworzyć obiekt typu unii, która nie ma nazwy?


Nie tworzymy wtedy obiektu, bo mamy już stworzony i po prostu nie możemy tworzyć kilku egzemplarzy unii.



IX. Czy do tego, by unia była anonimowa wystarczy, by nie miała nazwy?


Nie, nie może też pokazywać na nią żaden wskaźnik.



X. Czy można zdefiniować obiekty typu pola bitowego?


Nie.



XI. Wybierz poprawne warianty poniższego zdania. Pole bitowe może być typu:
a) signed int
B) double
c) long int
d) bool
e) unsigned int
f) enum
g) signed short
h) char


a), c), d), e), f), g), h)



XII. Który składnik w definicji pola bitowego można opuścić?
a) typ
B) nazwę
c) rozmiar(ile bitów)


Można opuścić nazwę.



XIII. Jeśli jakieś pole bitowe ma rozmiar zero bitów - co to oznacza?


Oznacza to, że chcemy aby następne pole bitowe było w kolejnym słowie.



XIV. Co to znaczy, że rozmieszczenie pól bitowych w słowie zależne jest od implementacji?


Zależne jest od której strony słowa kompilator zaczyna uzupelniać bity, oraz kiedy je urywa.



XV. Wybierz poprawne zakończenia następującego zdania. Pole bitowe:
a) może być typu bool
B) może być static
c) może mieć egzemplarz obiektu zdefiniowany globalnie
d) musi być składnikiem klasy/struktury
e) nie musi mieć nazwy, bo można na nie pokazać wskaźnikiem


a), c), d)



XVI. Napisz prosty program, który zapyta użytkownika o datę(np. urodzenia) żądając wprowadzenia jej jako jednej długiej liczby w postaci DDMMRRRR, gdzie DD oznacza dwucyfrowy numer dnia w miesiącu, MM dwucyfrowy numer miesiąca, a RRRR numer roku. Program ma przyjąć tę liczbę z klawiatury jako wartość typu long, a następnie wypisać na ekranie w postaci dziesiątkowej następujace jej fragmenty
- fragment o nazwie niebieski, na który składają się bity 0, 1, 2, 3, 4, 5
- fragment o nazwie zielony, na który składają się bity od 10 do 14(włącznie)
- fragment o nazwie czerwony, na który składają się bity 16,17,18.

W programie nie można ani raz użyć operacji bitowej koniunkcji ani przesunięcia bitowego. Jeśli posłużysz się unią, to niech NIE będzie ona anonimowa.

 

 

#include <iostream>
using namespace std;

int main()
{
struct ZiemniakPodzielony
{
unsigned long niebieski : 6;
unsigned long : 4;
unsigned long zielony : 5;
unsigned long : 1;
unsigned long czerwony : 3;
};

union Ziemniak
{
long data;
ZiemniakPodzielony ziemniakPodzielony;
};

Ziemniak ziemniak;

cout << "Podaj date urodzenia w formacie DDMMRRRR: " << endl;
cin >> ziemniak.data;

cout << "Niebieski: " << ziemniak.ziemniakPodzielony.niebieski << endl
<< "Zielony: " << ziemniak.ziemniakPodzielony.zielony << endl
<< "Czerwony: " << ziemniak.ziemniakPodzielony.czerwony << endl;

}

 

 

 

 

G8loSX2.png
  • Odpowiedzi 53
  • Dodano
  • Ostatniej odpowiedzi
Opublikowano

j) auto

nie w C++11

 

n) export

rownież nie, bo to keyword

 

definicja każe

 

zarezerwować miejsce w pamięci programu dla obiektu jakiegoś typu, a deklaracja

 

określa jaki typ zmiennych będzie przechowywał obiekt.

bez tego byłoby dobrze

 

zadanie XIII. zrobiłeś źle

w XIV. pomylileś centymetry z metrami (nazwa zmiennej, małe znaczenie, ale wychodzi nieścisłość)

 

Deklaracja określa jaki typ zmiennych będzie przechowywał obiekt.

a chociażby funkcje? to już nie są obiekty. Twoja definicja jest błędna

 

tyle się dopatrzyłem błędów tak na szybko

 

btw. chyba powinieneś każde zadanie opatrzeć w spoiler. I popracuj nad formatowaniem

 

@edit.

jeszcze chciałbym spytać.

dlaczego to nie jest zalecane?

f) _zmienna (dopuszczalny, ale nie zaleca się stosowania)

Opublikowano

f) _zmienna (dopuszczalny, ale nie zaleca się stosowania)

"Odradza się też zaczynać nazwę od znaku podkreślenia, bo często kompilator używa tego sposobu do własnych celów"

 

Dziękuję za pokazanie błędów, już zostały poprawione ;)

 

 

@Frezer212

Dziękuję, zostało już poprawione ;)

G8loSX2.png
Opublikowano

 

XIII. Napisz program, który z pomocą jednej instrukcji cout napisze na ekranie nastepujący tekst:

 

w i t a m y

na

p

o

kladzie

 

#include <iostream>

int main()
{
std::cout
        << "w i t a m y \n";
        std::cout << "na \n";
        std::cout << "p \n" << "o \n"<< "kladzie\n";
}  
 

Z tego co się orientuje to nie jest jedna instrukcja cout.

Opublikowano

2. Instrukcje sterujące – Ćwiczenia

I. Czym sterują poznane w tym rozdziale instrukcje sterujące?

 

Kolejnością działania programu.

 

II. Mamy wyrażenie logiczne (y < 0 , jakie mogą być jego
wartości?

 

True albo False

 

III. Czy w miejscu gdzie program spodziewa się wyrażenia
logicznego, można postawić na przykład obiekt(zmienną) typu całkowitego int?
Jak zareaguje program napotykając obiekt zamiast warunku?

 

Można, program będzie reagował tak:
jeśli zmienna będzie różna
od 0, będzie wskazywał na prawdę, a jeśli będzie równa 0, będzie mówił, że jest to fałsz.

 

IV. Załóżmy, że mamy obiekt typu int o nazwie a. Które z
następujących konstrukcji if są dopuszczalne?

 

int a;

// … nadanie wartości obiektowi a

a) if(a < 6) jakaś instrukcja;

(b if(a) jakaś instrukcja;

c) if(a+2) jakaś_instrukcja;

d) if( (a + 7)< (10 -2) ) jakaś instrukcja;
e) if((a+a)> (a – 4) ) jakaś_instrukcja;

 

V. W poniższym pseudo-kodzie trzykrotnie wystepuje słowo
kluczowe else. Do którego if należą tak umieszczone słowa else? Odpowiedz
podając naze warunku przy danym if.

 

 

if(warunek1)
{
If(warunek2) jakaś instrukcja;
If(warunek3) jakaś instrukcja;
else jakaś_instrukcja; // else nr. 1
}
else // else nr. 2
if(warunek4)
if(warunek5) jakaś_instrukcja;
else  // else nr 3
    jakaś instrukcja;

 

Else nr.1 należy do warunku3, else nr.2 należy do warunku1, a else nr.3 należy do
warunku5.

 

 

VI. Na czym
polega pętla programowa?

 

Na działaniu programu,
dopóki nie zostanie spełniony jakiś warunek.

 

VII. Które z trzech poznanych petli programowych mogą sprawić, że zawarte w nich
instrukcje(instrukcje będące ich treścią) nie będą wcale wykonane?

 

Pętla for, while

 

VIII. Jaka
jest zasadnicza różnica między pętlą programową zrealizowaną za pomocą:

 

a) instrukcji while;

(b instrukcji do-while;

Co z tej różnicy wynika?

Instrukcja while, najpierw sprawdza warunek i jeśli nie jest spełniony nie
wykona się ani razu, a pętla do while sprawdza warunek na końcu i wykona się co
najmniej raz, nawet jeśli warunek jest niespełniony.

 

IX. Kiedy w instrukcji for sprawdzany jest warunek – przed,
czy po obiegu pętli?

 

Przed obiegiem pętli.

 

X. Wewnątrz
nawiasu instrukcji for są dwa średniki. Po drugim z nich jest instrukcja, którą
roboczo nazwaliśmy instrukcją kroku pętli. Kiedy jest ona wykonywana -
przed czy po obiegu pętli?

 

Po obiegu pętli.

 

XI. Podaj przykłady realizacji nieskończonej pętli za pomocą trzech poznanych rodzajów
pętli(for, while, do while)

 

a) while(true) jakas_instrukcja;

(b for( ; ; ) jakas_instrukcja;
c) do jakas_instrukcja while(true);

 

XII. Pętla jest nazywana „nieskończoną”, gdy jej warunek
jest zawsze prawdziwy, więc nie
ma szansy, by przerwał on pracę tej pętli. Za pomocą jakich instrukcji można(z
pozycji programu) zakończyć pracę pętli i spowodować przejście do wykonywania
instrukcji po niej bezpośrednio następujących? Podaj dwa sposoby.

 

a) Za pomocą instrukcji break;

(b Za pomocą goto;

 

XIII. Jak można zakończyć prace nieskończonej pętli i przejść do o wiele dalszych
instrukcji, a nawet takich poprzedzających ją?(Czyli jakby „wrócić”)?

 

Za pomocą
instrukcji goto;

 

XIV. Jaka
jest różnica między obiektem zdefiniowanym w wyrażeniu inicjalizacyjnym pętli

for, a takim samym obiektem zdefiniowanym o jedną linijkę
powyżej tej pętli for?

 

Obiekt zdefiniowany w środku, ma tylko zakres lokalny wewnątrz pętli, poza już nie

można go wywołać, ani nic z nim
zrobić.

 

XV. Czy poprawna jest taka instrukcja switch?

 

 

int m;
// … nadanie wartości obiektowi m
switch(m)
{        
case 1:    
// …      
break;   
   
default:
// ...           
break;
    
case 5-2:     
// …       
break;
    
case 5-4:    
//…
}

 

 

Nie jest poprawna, gdyż case 1 oraz
case 5-4 się pokrywają.

 

XVI. Jakie konsekwencje ma nie umieszczenie instrukcji break po instrukcjach danej
etykiety case?

 

Nieumieszczenie break, będzie
powodowało wykonywanie kolejnych case’ów, pod casem,
który wywołaliśmy oraz dalszej części programu

 

XVII. Wyboru wielowariantowego można dokonać przy użyciu instrukcji switch lub if…else.
Przypomnij trzy aspekty, w których obie te instrukcje się różnią.

 

a) Przy instrukcji switch, musi być zmienna całkowita(int), lub wyrażenie typu
całkowitego, przy
if…else, nie ma to różnicy

(b Zmienna
wybierająca, musi być porównywana do stałej w instrukcji switch, a w instrukcji if…else może
być porównywana do zmiennej.

c) Switch – porównanie

do liczby x, if…else porównywanie
może być zmienne.

 

XVIII. Mamy dokonać wyboru wariantu działania programu
zależnie od ilości próbek
przebadanych przez układ pomiarowy. Jeśli jest ich 6, to podejmujemy działania,
jeśli jest ich 12, to działania, a w każdym innym przypadku działaniaC. Czy
można się w tym celu posłużyć instrukcją sterującą switch?

 

Można.

 

XIX.
Zadanie podobne do poprzedniego, lecz nieco zmienione. Mamy dokonać wyboru
wariantu działania programu zależnie od ilości próbek przebadanych przez układ
pomiarowy. Jeśli jest ich 6, to podejmujemy działania, jeśli jest ich 12 to
działania B, a jeśli więcej niż 12, to działaniaC. Czy można się w tym celu
posłużyć instrukcją switch?

 

Nie można.

 

XX. Mamy dokonać wyboru wariantu działania programu zależnie od wielkości przychodu
wyrażonego w złotych(bez groszy). Są trzy progi podatkowe(stałe). Zależnie od
wielkości dochodu(między którymi jest progami) podatek oblicza jedna z czterech
procedur. Czy można się tu posłużyć instrukcją switch do wybrania odpowiedniej
procedury?

 

Nie, dlatego, że są to zmienne.

 

XXI. Jakie
działanie może mieć instrukcja break umieszczona w pętlach for, while,
do-while? Jak działa w przypadku, gdy te pętle są zagnieżdżone?

 

"Przełamuje”
tylko jedną pętle.

 

XXII. Jaką
instrukcją sterującą możemy posłużyć się, by wydostać się z wielokrotnie
zagnieżdżonych pętli?

 

Instrukcją goto;

 

XIII. Co to
jest etykieta?

 

Nazwa zakończona dwukropkiem.

 

XXIV. Jakie
działanie w pętlach ma instrukcja continue?

 

Przechodzi od razu do kolejnego obiegu pętli.

 

XXV. Jeśli
w trakcie wykonywania treści pętli for napotkana zostanie instrukcja continue,
to co najpierw zostanie wykonane – sprawdzenie warunku, czy instrukcja krokowa?

 

Instrukcja krokowa.

 

 

G8loSX2.png
Opublikowano

II. Mamy wyrażenie logiczne (y < 0 , jakie mogą być jego wartości?

W odpowiedzi napisać lepiej "Wszystkie liczby mniejsze od zero" lub "Wszystkie liczby ujemne".

IV. Załóżmy, że mamy obiekt typu int o nazwie a. Które z

 

następujących konstrukcji if są dopuszczalne?

Według mnie a) i d) również są dopuszczalne.

VII. Które z trzech poznanych petli programowych mogą sprawić, że zawarte w nich

 

instrukcje(instrukcje będące ich treścią) nie będą wcale wykonane?

Podałeś tylko 2 pętle.

Dalej nie chce mi się czytać :F

Opublikowano

IV. Zostaje przy swoim. Te zapisy są jak najbardziej poprawne i działają jak należy. Znaku "_" używa się, gdy zadeklarowałeś zmienną o nazwi np. double To_zmienna; Więc ten znak nie ma nic do do tego zadania. :E

VII. Racja, nie zauważyłem.

Opublikowano

 

 

II. Mamy wyrażenie logiczne (y < 0 , jakie mogą być jego wartości?

W odpowiedzi napisać lepiej "Wszystkie liczby mniejsze od zero" lub "Wszystkie liczby ujemne".

 

co do II to się nie zgodzę. To wyrażenie może przyjąć jedynie wartości true/false.

 

 

 

IV. Załóżmy, że mamy obiekt typu int o nazwie a. Które z

 

 

następujących konstrukcji if są dopuszczalne?

Według mnie a) i d) również są dopuszczalne.

 

w IV wszystkie są poprawne.

jakas instrukcja nie reprezentuje nazwy, tylko pełni funkcje jakby wytłumaczenia co ma się dalej dziać

 

btw. po nazwie instrukcji (jak wymieniasz je w zadaniach) nie dawaj średników, bo nie jest to część jej nazwy.

Opublikowano

3. Typy - Ćwiczenia


I. Deklaracja jest wyjaśnieniem czegoś kompilatorowi na temat naszego programu. Jeśli deklarujemy nazwę nnn, to wyjaśniamy, że co?

Wyjaśniamy, że nazwa nnn, jest jakiegoś typu



II. Wyjaśnij jaka jest różnica między definicją, a deklaracją. Czy są to pojęcia rozłączne, czy też jedno jest szczególnym rodzajem drugiego? Jeśli tak, to które jest rodzajem którego?

Deklaracja jest to wyjaśnienie, że dana nazwa jest jakiegoś typu, a definicja do tego rezerwuje miejsce w pamięci niej. Definicja jest równocześnie deklaracją.



III. Czy możliwe jest powtórzenie tej samej deklaracji w danym zakresie ważności?

Nie(nie zawsze).



IV. Czy możliwe jest powtórzenie tej samej definicji w danym zakresie ważności?

Nie.



V. Co powołuje do życia obiekt o nazwie nnn. Jego deklaracja, czy definicja?

Definicja



VI. Jaka jest relacja między typami złożonymi, a typami fundamentalnymi?

Typ złożony – składa się z typów fundamentalnych



VII. Wymień typy przeznaczone do pracy z liczbami całkowitymi. Podaj ich nazwy w wariantach „ze znakiem” i „bez znaku”.

signed int, unsigned int, signed short, unsigned short, signed long, unsigned long, char, long long



VIII. Jeśli przy deklaracji obiektu typu int nie zaznaczyliśmy czy chodzi o wersję „ze znakiem”, czy „bez znaku” – który wariant wybierze kompilator?

Wersję ze znakiem



IX. Co to są znaki alfanumeryczne?

Znaki alfabetyczne + numeryczne, pojedyncze litery, numery + znaki specjalne



X. Podaj nazwę typu mogącego przechowywać znaki alfanumeryczne z podstawowego zestawu(np. ASCII).

Char



XI. Jeśli w w powyższym typie nie zaznaczyliśmy czy chodzi o wersję „ze znakiem”, czy „bez znaku” – który wariant wybierze kompilator?

Zależnie od kompilatora



XII. Podaj nazwę typu przeznaczonego do przechowywania rozszerzonego zestawu znaków alfanumerycznych.

wchar_t



XIII. W języku C typ przeznaczone do przechowywania rozszerzonego zestawu znaków alfanumerycznych uzyskany jest dzięki typedef. Instrukcja ta( jak już wiemy) nie tworzy nowego typu, ale nadaje nową , dodatkową nazwę jakiemuś już istniejącemu). Czy w C++ typ ten jest odrębnym typem, czy może stworzonym przez typedef?

Odrębnym



XIV. Wymień trzy typy przeznaczone do pracy z liczbami zmiennoprzecinkowymi. Czy stosuję się do nich specyfikatory signed/unsigned?

float, double, long double – nie stosuje się.



XV. Wymień nazwę typu przeznaczonego do pracy ze zmiennymi logicznymi. Ile różnych wartości może przyjmować obiekt takiego typu? Jakie to wartości?

bool, dwie wartości – true, false



XVI. Jakie naprawdę wartości liczbowe reprezentują możliwe „stany” obiektu typu logicznego .

True – 1, False – 0


XVII. Czy do typu bool można zastosować specyfikator signed?

Nie



XVIII. Jeśli dany kompilator rezerwuje dla typu short int dwa bajty pamięci(czyli 16 bitów) to liczbę z jakiego przedziału można w nim zapisać? Podaj w przybliżeniu , w zaokrągleniu do tysięcy.

-32000 do 32000



XIX. Co zrobić, jeśli jakaś ujemna liczba nie mieści się w obiekcie typu short int? Jakim innym typem można wtedy się posłużyć?

Int, long int



XX. Gdzie definiować można obiekty w języku C++:


Jedynie powyżej instrukcji wykonywalnych,
Nawet wśród instrukcji wykonywalnych.



XXI. Jeśli mamy pętle for, w której instrukcji inicjalizującej jest definicja obiektu o nazwie „i”, to czy w instrukcji postawionej bezpośrednio po zakończeniu pętli możemy zdefiniować nowy obiekt o nazwie „i”?

Tak



XXII. W wyrażeniu warunkowym instrukcji if można definiować obiekt. Jaki zakres ważności ma ten obiekt?

W bloku if, oraz należącego do niego else



XXIII. Co to jest stała dosłowna? Czy obiekt stały mieszczący w sobie wartość 3.14 – to jest stała dosłowna?

Stałe dosłowne to tylko wartości. To nie jest stała dosłowna.



XXIV. Zapisz tę samą wartość np. 17 w postaci stałej dosłownej w zapisie dziesiątkowym, ósemkowym i szesnastkowym.


17 = 021 = 0x11



XXV. Zapisz wartość 10 w postaci stałej dosłownej typu: int, long, unsigned int, unsigned long, dobule, float.

10, 10L, 10u, 10uL, 10. = 1e1, 10.F



XXVI. Zapisz liczbę 15.6 w postaci stałej dosłownej typu double oraz float. Użyj najpierw zapisu dziesiętnego(zwykłego), a następnie wykładniczego.


double:15.6e1, 15.6
float: 15.6e1F, 15.6F



XXVII. Mogą być tylko dwie stałe dosłowne typu bool. Podaj je.

0, 1



XXVIII. Jakiego typu jest nastepująca stała znakowa ‘w’?

char



XXIX. Zapisz stałe dosłowne reprezentujące następujące znaki specjalne: tabulator, znak nowej lini, odwrotny ukośnik, sygnał dźwiękowy?


Tabulator – ‘\t’
Nowa linia – ‘\n’
Backslash – ‘\\’
Sygnał dźwiękowy – ‘\a’



XXX. Zapisz jako stałą dosłowną znak o kodzie 2f(szesnastkowo).

47



XXXI. Zapisz jako stałą dosłowną znak o kodzie 10(ósemkowo).

8



XXXII. Zapisz jako stałą dosłowną literę m, tak by owa stała była typu wchar_t.

L’m’



XXXIII. Zapisz w postaci stałej dosłownej typu C-string swoje imię i nazwisko. Następnie miedzy imię i nazwisko wstaw znak nowej linii.

”Imię \nNazwisko”



XXXIV. Co zrobic, jeśli stała dosłowna typu C-string jest tak długa, że nie możemy jej zmieścić w jednej linii tekstu programu. Czy można dokończyć jej pisanie w linii następnej? Jak to zrobić, by ostatecznie uzyskać i tak jeden długi C-string?

Nie można tego, dokończyć w linii następnej. Trzeba w jednej linii zamknąć cudzysłów i od drugiej linii znowu otworzyć i napisać resztę zdania, tak jak np. tutaj:
std::cout << „Bardzo długi długi długi długi długi długi długi długi długi długi długi długi”

„C-String”[/color][/code]



XXXV. Jaka jest relacja między typami złożonymi, a typami fundamentalnymi?

Typ złożony jest zbudowany z typów fundamentalnych i operatora



XXXVI. Czy void to typ fundamentalny, czy złożony?

Fundamentalny



XXXVII. Czy można definiować obiekt typu void?

Nie, typ void tylko w deklaracji typu złożonego



XXXVIII. Co to jest czas życia obiektu?

”Okres od momentu, gdy zostaje on zdefiniowany, do momentu gdy przestaje istnieć”



XXXIX. Co to jest zakres ważności nazwy obiektu?

Zakres, w którym dany obiekt jest dostępny



XL. Jaka jest różnica między powyższymi dwoma pojęciami?

Obiekt może istnieć, ale nie być dostępny



XLI. W tzw. Bloku, czyli fragmencie programu ujętym w znaki klamry {}, definiujemy gdzieś obiekt o nazwie m. Jaki zakres ma ta nazwa, czyli od jakiego miejsca w programie ta nazwa jest znana i kiedy przestaje być znana. Czy do takiej nazwy można się do niej odnieść spoza tego bloku?

Taka nazwa jest znana tylko od momentu jest zdefiniowania do końca bloku. Przestaje być znana po skończeniu się bloku, oraz nie można się do niej odnieść.



XLII. To pytanie jest dla wtajemniczonych – wiedzących, co to jest funkcja, Czy za pomocą instrukcji Goto można przeskoczyć do wnętrza innej funkcji? Jaki zakres ma etykieta? Czyli o jakiego miejsca w programie ta nazwa jest znana i kiedy przestaje być znana?

Etykieta ma zakres ważności funkcji, znana w całej, niezależnie gdzie jest oraz nie jest znana poza funkcją



XLIII. Co to znaczy, że nazwa jest globalna. Jeśli na program składa się z kilka plików źródłowych, to czy nazwa globalna z jednego z nich jest znana w pozostałych?

Nazwa globalna jest znana w całym pliku i nie jest znana w innych plikach źródłowych.



XLIV. W danym programie po służyliśmy się dyrektywą
#include <iostream>
Co zrobić, by moc odnosić się do nazwy cout bez konieczności używania kwalifikatorów zakresu(std::cout). Podaj dwa sposoby.

Po linkowaniu bibliotek dodać dyrektywę: using std::cout



XLV. Na czym polega zasłonięcie nazwy globalnej przez nazwę lokalną?

Gdy istnieje nazwa globalna, możemy stworzyć taką samą lokalnie ale będzie „żyła” tylko w bloku.



XLVI. Jak z lokalnego bloku, w którym globalna nazwa została zasłonięta przez nazwe lokalną –odnieść się do zasłoniętej nazwy globalnej?

Poprzez operator::



XLVII. Jeśli mamy zagnieżdżone dwa bloki, a w tym głębiej zagnieżdżonym – lokalna nazwa załania inną lokalną – to jak możemy odnieść się do tej zasłoniętej nazwy lokalnej?

Nie możemy się do niej odnieść.



XLVIII. Jaka jest różnica między inicjalizacją, a przypisaniem?

Inicjalizacja to początkowe nadanie wartości, a przypisanie to późniejsze nadawanie wartości temu samemu obiektowi



XLIX. Czy można przypisać jakąś wartość do przed chwilą utworzonego obiektu z przydomkiem „const”?

Nie.



L. Co daje przydomek „register”?

Obiekt wtedy jest dodawany do rejestru, czyli miejsca szybkiego dostępu w programie(jest to zależne od kompilatora).



LI. Jaki jest cel stosowania przydomka „volatile” . O czym informuje on kompilator?

Informuje on kompilator, o tym, że obiekt może zmieniać swoją wartość bez jego wiedzy i ma na niego uważać.



LII. Do czego służy instrukcja typedef? Czy dzięki niej tworzymy nowy typ?

Tworzymy jedynie synonimy danego typu, ułatwiając sobie prace.



LIII. Czy instrukcja enum tworzy nowy typ, czy może jej rezultat jest wariantem innego fundamentalnego typu?

Tworzy osobny typ.



LIV. Jeśli na liście wyliczeniowej pierwszej nazwie nie przypiszemy żadnej wartości, to jaką wartość otrzyma ona przez domniemanie?

0



LV. Jeśli na liście wyliczeniowej jednej z kolejnych nazw nie przypiszemy żadnej wartości, to jaką wartość otrzyma ona przez domniemanie?

Liczbę o 1 większą poprzedniej



LVI. Czy typ wytworzony przez enum jest typem zmiennoprzecinkowym, czy może całkowitym?

Całkowity



LVII. Czy na liście wyliczeniowej możemy umieścić stałą dosłowną 3.14?

Nie



LVIII. Mamy dwa typy wyliczeniowe. Tak się składa, że w jednym nazwa xxx reprezentuje stałą wartość 89. Jeśli w drugim z nich jest nazwa yyy, która także reprezentuje wartość 89, to czy w kontekstach, gdzie program spodziewa się nazwy xxx, można posłużyć się nazwą yyy?

Nie

 

 

G8loSX2.png
Opublikowano

Wyjaśniamy, że nazwa nnn, jest jakiegoś typu

raczej wyjaśniamy, że nazwa nnn może być używana w dalszym kodzie w ustalonej postaci

 

 

III. odpowiedź to nie (nie zawsze).

 

VII. jeszcze char. Można jeszcze dodać informacje o long long (w standardzie od c++11)

po części również bool przechowuje całkowitoliczbowe wartości

 

XXVI

double:156e1, 15.6

float: 156e1F, 15.6F

156e-1 powinno być

albo poprawniej

1.56e1

 

 

Nie można tego, dokończyć w linii następnej. Trzeba w jednej linii

zamknąć cudzysłów i od drugiej linii znowu otworzyć i napisać resztę

zdania, tak jak np. tutaj:std::cout << Bardzo długi długi długi długi długi długi długi długi długi długi długi długi

<< C-String

niekoniecznie

string lol = "asdasdasdsadasdasdadsd"
             "asdadasdsadasdasdasdsadsadasdadsa";

to się kompiluje

 

 

Obiekt wtedy jest dodawany do rejestru, czyli miejsca szybkiego dostępu w programie.

teoretycznie. W praktyce kompilator i tak zrobi to co uważa za słuszne

 

tyle na razie, dużo tego, więc możliwe, że coś przeoczyłem

Opublikowano

VII. Wymień typy przeznaczone do pracy z liczbami całkowitymi. Podaj ich nazwy w wariantach „ze znakiem” i „bez znaku”.

Teoretycznie char też jest typem liczb całkowitych (8 bitowych).

Opublikowano

Ja tez nie jestem nieomylny, wiem, że na niektóre pytania można odpowiedzieć lepiej, a może i gdzieś się walnąłem. Miło by było, gdyby ktoś jeszcze skorygował moje poprawki, jeśli znalazłby w nich błąd.

Opublikowano

4. Operatory – Ćwiczenia


I. Co to znaczy, że operator jest dwuargumentowy lub jednoargumentowy. Wyjaśnij to na przykładzie dwóch operatorów: dwuargumentowego(minus) i jednoargumentowego(minus). Są to dwa różne operatory oznaczane tym samym symbolem.

Dwuargumentowy – działa na dwóch argumentach: 2 - 1
Jednoargumentowy – działa na jednym argumencie : -1


II. Posługując się operatorem „reszta z dzielenia” napisz program, który wypisywał będzie na ekranie kolejne liczby całkowite począwszy od 1 do 100, a po zakończeniu każdej 10stki wypisze „zakończona dziesiątka”

 

 

#include <iostream>
int main()
{
for(int i = 1; i<=100;++i)
{
std::cout << i << '\t';
if(!(i%10)) std::cout << "zakonczona dziesiatka!\n";
}
}

 


III. Używając operatora „reszta z dzielenia” – napisz program, który będzie wypisywał na ekranie kolejne litery alfabetu. Pierwszych osiem (A-H) ma być wypisywanych po dwie litery w jednym rzędzie, a co do następnych, to program ma zadać użytkownikowi pytanie(po ile liter w rzędzie ma wypisywać dalej). Zależnie od tej odpowiedzi następne litery mają być wypisywane wg. nowej zasady.

 


#include <iostream>
using namespace std;

int main()
{
short kolumny = 2, numerowanie = 1;

for( char litera = 'A'; litera <= 'Z'; litera++, numerowanie++)
{
cout << litera;
if( numerowanie % kolumny) cout << "\t";
else cout << "\n";

if( litera == 'H')
{
numerowanie = 0;
cout << "Po ile liter w rzedzie mam wypisywac? ";
cin >> kolumny;
if (kolumny==0) return 0;
}
}

cout << endl;
}

 


IV. Jak jest różnica między operatorem preinkrementacji(++x), a operatorem postinkrementacji(x++)?

Preinkrementacja, od razu podnosi wartość o 1, a preinkrementacja dopiero później(W niektórych przypadkach preinkrementacja jest szybsza niż postinkrementacja.


V. Jaka liczba pojawi się na ekranie na skutek działania następujących instrukcji
int a = 4;
cout << (a = 7) << endl;

7


VI. Jaka jest różnica między operatorami arytmetycznymi, a logicznymi – jeśli chodzi o typ rezultatu.

Operatory arytmetyczne dają rezultat w kształcie liczby, a logiczne true/false


VII. Omów różnicę między operatorem =, a operatorem ==

= - operator przypisania
== - operator porównania


VIII. Który z operatorów =, == może się znaleźć wyrażeniu warunkowym instrukcji if ? Czyli czy poprawne są konstrukcje:
A if(x = y)
B if(x == y)
Co zrobić by uniknąć tu ostrzeżeń kompilatora?

Obie konstrukcje są poprawne jeśli dajemy je świadomie, przy czym opcja A musi mieć ( (x = y) ), aby uniknąć ostrzeżeń.


VIX. Jaka jest wartość wyrażenia napisanego poniżej( w drugiej linijce).
bool ruch = false;
!!!ruch;

True


X. W wyrażeniu warunkowym instrukcji if może wystąpić nawet kilka operatorów logicznych. Załóżmy, że obiekty a, b, c są typu int. W poniższej instrukcji widzimy więc trzy człony alternatywy.
if((a < b ) || ( a < 15) || (a > (c = 15) ) { /*…*/ }
Pytanie 1: Który człon obliczony zostanie najpierw i jakie będą następne.
Pytanie 2: Wyjaśnij działanie członu trzeciego.
Pytanie 3. Oto instrukcja, która logicznie odpowiada powyższej

if( (a > ( c = 15) ) || (a < b ) || (a < 15) ) { /*…*/}
Wytłumacz jaka jest między nimi różnica, jeśli chodzi o końcową wartość obiektu c.

Pytanie 1: a < b, a < 15, c = 15, a > c
Pytanie 2: Człon trzeci najpierw przypisuję do c liczbę 15, a potem sprawdza czy a jest większe od c.
Pytanie 3: Tu na pewno c otrzyma wartość 15, w pierwszym wyrażeniu mogła nie dostać, jeśli któraś alternatywa zostałaby spełniona wcześniej


XI. To ćwiczenie jest na sprawdzenie zrozumienia różnicy między operatorami logicznymi a bitowymi. W tabelce podane mamy dwa obiekty(dla uproszczenia 16 bitowe) Podaj rozkład bitów wartości wyrażeń występujących w dalszej części tabeli.


Short int a; - 0000 1111 0000 1111
Short int b; - 0000 0000 0000 1111
Wypełnij rozkłady bitów dla poniższych wyrażeń
a & b - 0000 0000 0000 1111
a && b - 0000 0000 0000 0001
a | b - 0000 1111 0000 1111
a || b - 0000 0000 0000 0001


XII. Wyjaśnij działanie operatora += w poniższym fragmencie
int m = 3;
m += 2;
Podaj jaką wartość na skutek tych instrukcji będzie miał obiekt m.

Zwiększenie zmiennej m o 2( m = m +2 ), wartość końcowa = 5.


XIII. Na argumentach jakich typów pracuje operator przesunięcia w lewo(<<). Czym zapełniany jest bit z prawego brzegu słowa? Zerami czy jedynkami?
Co się dzieje z najbardziej znaczącym bitem?

Pracuje na całkowitych, prawy brzeg zapełniany jest zerami, najbardziej znaczący bit tracimy.


XIV. Napisz jak będzie wyglądał rozkład bitów w obiekcie rezultat po wykonaniu poniższych instrukcji.
short int a = 0xf (0000 0000 0000 1111)
short int rezultat = a << 2

0000 000 0011 1100


XV. Operator przesunięcia >> przesuwa bity danego słowa o żądaną ilość miejsc w prawo . Co, po przesunięciu, dzieje się z najmniej znaczącym bitem?

Tracimy go.


XVI. Jeśli chodzi o uzupełnianie bitów z lewej strony słowa przez operator >>, może to zależeć od implementacji. Są jednak sytuacje, gdy mamy pewność, że najbardziej znaczący bit będzie wypełniany zerami. Z jakim typem obiektu powinniśmy pracować, by mieć tę pewność?(Wiadomo, że musi to być obiekt typu całkowitego, ale z jakim „przydomkiem”?)

Unsigned, bądź signed dodatnie.


XVII. Jak zmieni się wartość obiektu x na skutek poniższych instrukcji?
int x = 0;
x =-1;
x -= 1;

x = -1
x = x – 1
x = -2


XVIII. Ile razy trzeba przesunąć w lewo bity poniższego obiektu by w rezultacie jego wartość została pomnożona przez 1024?
int ddd = 3;

ddd <<= 10


XIX. Załóżmy, że mamy obiekt typu int o nazwie x. Podaj wartość poniższego wyrażenia, gdy x = 100.
(x % 100) ? „Krakow” : „Londyn”

”Londyn”


XX. Mamy obiekt typu double o nazwie aaa. Które z poniższych wyrażeń jest poprawne?


A sizeof(aaa)
B sizeof(double)

C sizeof(double + 2)
D sizeof(double) + 2


XXI. Mamy obiekt typu double o nazwie mm. Napisz dwie formy zastosowania tzw. Tradycyjnego rzutowania tego obiektu na typ int. Na czym polega „stratność” takiego rzutowania?

(int)mm
Stracimy liczby po przecinku.


XXII. Co jest wartością następującego wyrażenia
(55.2 , 12, x++, a = b + 6, 4)

4


XXIII. Co to znaczy, że dany operator ma wyższy priorytet niż inny?

To znaczy, że zostanie wcześniej wykonany.


XXIV. Jak – nie pamiętając priorytetów operatorów – można mimo wszystko zapanować nad kolejnością obliczania danego skomplikowanego wyrażenia?

Za pomocą nawiasów.


XXV. Jaka jest łączność operatorów) jednoargumentowych?

Prawostronna


XXVI. Poniżej widzisz fragment kodu. Ostatnia instrukcja to przypisanie. Ujmij w nawiasy poszczególne człony tego przypisania – tak aby nawiasy nie zmieniły kolejności obliczania wyrażenia.
int a, b, c, d;
b = 15;
d = 2;
a = b = c = d

(a =( b = (c = d) ) ) Ostatecznie 2.


Jaka wartość ostatecznie znajdzie się w poszczególnych obiektach?
XXVII. Ujmij w nawiasy poszczególne człony wyrażenia mnożenia – tak, by nawiasy nie zmieniły kolejności obliczania wyrażenia.

int a, b, c, d, rezultat;
rezultat = a * b * c * d ;

( ( (a* B) * c ) * d)


XXVIII. Jaka jest łączność operatorów dwuargumentowych?

Lewostronna, jedynie przypisanie jest prawostronne.

 

 

 

G8loSX2.png
Opublikowano

II. Kod nie wykonuje zadania

poprawny kod

#include <iostream>
int main()
{
    for(int i = 1; i<=100;++i)
    {
        std::cout << i << '\t';
        if(!(i%10)) std::cout << "zakonczona dziesiatka!\n";
    }
}

III. spoko, ale wrzucę swoje podejście

#include <iostream>
using namespace std;
int main()
{
    int iloscLiterWRzedzie = 2;
    for(char a = 'A', i = 1; a <= 'Z'; ++a, ++i)
    {
        cout << a;
        if(a == 'H')
        {
            cout << "\npodaj nowa ilosc: ";
            cin >> iloscLiterWRzedzie;
            i=0;
        }
        if(i%iloscLiterWRzedzie==0)
        {
            cout<<'\n';
        }
    }
}

IV. warto dodać, że preinkrementacja w niektórych przypadkach jest szybsza od postinkrementacji, ponieważ nie jest konieczne tworzenie kopii obiektu

XX. C nie jest poprawne

 

XXI.

mm(int) jest niepoprawne

drugim sposobem jest int(mm)

 

XXVII. Emotka się wkradła. W opcjach zaawansowanego edytora wyłącz używanie emotikon z prawej strony

Opublikowano

4.IV. Chyba bardziej precyzyjnym stwierdzeniem byłoby, że preinkrementacja najpierw zwiększa swoją wartość o jeden, a później zwraca wartość, a postinkrementacja najpierw zwraca wartość, a później zwiększa o jeden. Prosty przykład:

 

int i = 0;
cout<<++i; //wyświetli na ekranie 1
cout<<i++; //dalej wyświetli 1
cout<<i; //wyświetli już dwa

LeSSter jak już wkleiłeś :P.


Pomagam w projektach dotyczących programowania (C++/C/Java/C#/inne). Jak masz jakiś problem, napisz do mnie, wspólnie poszukamy rozwiązania ;).

Opublikowano

Ja ze swojej strony moge polecić stronke z odpowiedziami do symfoni: www.cplusplus.xaa.pl
Możesz wykorzystać jako dodatkowe źródło do sprawdzenia (choć nie ręczę że wszystkie informacje są tam poprawne). Jeśli przy sprawdzaniu zauważysz jakiś błąd możesz zostawić komentarz pod danym rozdziałem lub wysłać mi PW na forum :)

 

Przydatny temat założyłeś :)Sam męcze właśnie symfonie (już nie wiem który to z kolei raz) i przyznam że spisywanie odpowiedzi motywuje do dalszej nauki.

 

Pozdrawiam i życzę sukcesów!

void_bit.jpg

Opublikowano

5. Funkcje - Ćwiczenia

 

 

I. W danym miejscu programu wywołujemy funkcję f. Czy przed tym wywołaniem powinna wcześniej nastąpić definicja tej funkcji, czy deklaracja tej funkcji?

Deklaracja


II. Jak wygląda operator wywołania funkcji? To znaczy, czym różni się wywołanie funkcji od podania jej nazwy?

Operator: nazwafunkcji(), różni się nawiasami.


III. Przeczytaj następujące deklaracje funkcji. Które z nich są niepoprawne?


A int fa();
B void fb(int);
C void fc(void);

D double fd(int, void);
E Fe(double, char);
F void ff(double, int, int, char, int, int);
G void fb(int liczba);

H int fb(double wspolcz, int char znak);


IV. Mamy deklarację funkcji


int f();
a w ciele tej funkcji znajduje się instrukcja
return 4.2;
Jaką wartość zwróci funkcja f?

Zwróci wartość 4.


V. Mamy deklarację funkcji


double f2() ;
A w ciele tej funkcji znajduje się instrukcja
return 4;
Jaką wartość zwróci funkcja f2?

Zwróci wartość 4.0 .


VI. Co się stanie, jeśli w funkcji
void f5();
znajdzie się instrukcja
return 0;

Wystąpi błąd kompilacji.


VII. Czy poprawne są następujące deklaracje

A int man1();
B man2();
C int main();

 

Tylko A, jest poprawne.


VIII. Gdzie w programie jest deklaracja funkcji main ?

Definicja, jest równocześnie deklaracją.


IX. Mamy takie dwie realizacje funkcji main ?


int main()
{
return 1;
}
Oraz
int main()
{

}
Która z nich jest poprawna?

Obydwie.


X. W naszym programie, oprócz funkcji main mamy funkcje fff o następującym ciele


double fff()
{
int m = 6 +3;
main();
return 0,5 +m ;
}
Czy to poprawne?

Tak


XI. Funkcja main jest zdefiniowania w taki sposób
Int main()
{
return 33;
}
Gdzie dotrze wynik pracy tej funkcji?(liczba 33)

Do systemu operacyjnego, bądź programu, który potrzebował zwrotu tej liczby.


XII. Co to są argumenty formalne funkcji?

Argumenty, które funckja sobie "przezywa".


XIII. Co to są argumenty aktualne funkcji?

Te, które są wysyłane do funkcji.


XIV. Co to są argumenty wywołania funkcji?

Te same, co argumenty aktualne


XV. Oto dwie funkcje:


void pierwsza();
double druga(char z, int k)

void pierwsza()
{
// …
char cc = 'x'
int m = 8
double r = druga(cc, 7);
double y = druga('h', m);
}
Widzisz tu dwa wywołania funkcji druga. Dla obu przypadków wywołań wymień nazwy argumentów formalnych funkcji druga. Dla obu wywołań wymień jej argumenty aktualne.

Argumenty formalne funkcji druga: z, k
Argumenty aktualne:
double r: cc, 77
double y: 'h', m


XVI. Mamy dwie funkcje

 

void f1(int n)
{n++}
//-------
void f2(int &n)
{
n++;
}
Jaki otrzymamy wydruk na ekran pochodzący z poniższego fragmentu programu?
void g()
{
int liczba = 10 ;
f1(liczba);
cout << "liczba = " << liczba << endl;
f2(liczba);
cout << "liczba = " << liczba << endl;
} 

liczba = 10
liczba = 11


XVII. Wymień dwa poznane dotychczas sposoby przesłania argumentów. Który może zmodyfikować wartość obiektu wysłanego do funkcji, a który nie?

Przez referencję oraz wartość. Przez wartość wysyła tylko kopie, a referencja posługując się "przezwiskiem" modyfikuje go.


XVIII. W programie składającym się z wielu plików, wielokrotnie używana jest funkcja mająca jeden argument domniemany typu double. Jego domniemana wartość to 7.5 Funkcja ta zdefiniowana jest w pliku zzz.cpp
Wiemy, że deklaracja tej funkcji musi się znaleźć w każdym pliku, który z tej funkcji zamierza skorzystać, (albo w jednym pliku nagłówkowym włączanym do wszystkich tych plików).
W którym miejscu programu powinna się znaleźć informacja o domniemaniu wartości tego argumentu?

Przed pierwszym użyciem tej funkcji.


XIX. Czy możliwa jest funkcja, która ma wszystkie argumenty domniemane?

Tak


XX. Czy możliwa jest funkcja, która ma domniemaną wartość rezultatu?

Tak.


XXI. Funkcja ma mięc dwa argumenty, z których jeden ma mieć wartość domniemaną, drugi jest zwykły. W jakiej kolejności mogą one wystąpić w deklaracji tej funkcji?

Najpierw zwykły, potem domniemany.


XXII. Dana jest funkcja
void f(int a, int b = 2, int c =3);
Można ją wywołać na przykład tak:
f(1, 2, 3);
Wymień wszystkie pozostałe możliwe sposoby wywołania tej funkcji nadające argumentom formalnym tę samą wartość, jaką nadaje powyższe wywołanie.

f(1); f(1,2)


XXIII. Napisz deklarację funkcji o nazwie fx, która zwraca rezultat typu bool, a wywoływana jest z dwoma argumentami. Pierwszy z nich jest typu char i jego wartością domniemaną jest 'g'. Drugi jest typu double i jego wartością domniemaną jest 12.5

bool fx(char y = 'g', double x = 12.5)


XXIV. Załóżmy, że poprawna jest deklaracja umieszczona poniżej w pierwszej linii. Czy poprawne jest wystąpienie zaraz za nią tych następnych w takiej właśnie kolejności? Jeśli nie, wskaż błędne.


A void f(int a, double, char c);
B void f(int a, double, char c = '2');
C void f(int a, double = 3, char c);

D void f(int a. double = 3, char = '6')

 

A, B, C są poprawne.


XXV. Czy poprawny jest następujący prosty program?

 

#include <iostream>
using namespace std;
void fun(int a, double  { }
double x = 1.1; 
double y = 8.8;
int main()
{ 
int zero = 0; 

fun(1, 6.6); 
{ 
void fun(int a = -1, double b = y);
fun(); 
if(2 > zero) 
{ 
void fun(int a, double b = x ); fun(zero);
} 
}
}

Jeśli nie, to dlaczego? Jak go poprawić, by jego działanie się nie zmieniło, ale dawał się kompilować poprawnie?

Nie kompilował się z powodu braku dostępu do zmiennej x, trzeba było ją zmienić aby była globalna jak wyżej.


XXVI. Czy możliwe jest, by funkcja, której deklaracja nie przewiduje żadnych argumentów domniemanych, w jakimś lokalnym zakresie miała zdefiniowane argumenty domniemane?

Tak, możemy ustalić lokalnie nowe argumenty domniemane, ale bedą tylko tu ważne.


XXVII. Jeśli zdecydowaliśmy, że jeden z argumentów formalnych funkcji f nie będzie w niej użyty, mimo, że inne funkcje tę funkcję f często z odpowiednim argumentem aktualnym wywołują, to gdzie należy zrobić zmianę określającą dany argument jako nienazwany? W definicji czy deklaracji funkcji?

W definicji.


XXVIII. W którym miejscu programu składającego się z jednego pliku – należy umieścić definicję funkcji inline? Jak postąpić, gdy program składa się z kilku plików?

Na samej "górze" programu, gdy program składa się z kilku plików trzeba umieści jej "zewnętrzną"(extern) deklarację w pliku nagłówkowym, bądź każdym pliku programu..


XXIX. Napisz program składający się z funkcji main i funkcji druga będących w dwóch różnych plikach. Następnie napisz definicję funkcji inline o nazwie wieksza, która przyjmuje dwa argumenty typu int, a jako rezultat zwraca większy z nich. Wywołania tej funkcji mają być zarówno z funkcji main, jak i z funkcji druga.
Zrób to na dwa sposoby:
1 używając pliku nagłówkowego włączanego dyrektywą #include,
2 bez użycia pliku nagłówkowego.

 

header.h

 

 

 

#include <iostream> 

using namespace std;

inline int wieksza(int a, int 
{
        return (a >  ? a : b;
}

void druga();

 

 

main.cpp

 

 

 

#include "header.h"

int main()
{
        druga();
        cout << wieksza(2, 3) << endl;
        
}

 

 

druga.cpp

 

 

 

#include "header.h"

void druga() 
{
        cout << wieksza(2, 3) << endl;
}

 

 

 

 


XXX. Jaki zakres ważności ma nazwa zdefiniowana w pliku programu poza wszelkimi funkcjami? Jak rozciąga się ten zakres ważności?

Globalny, rozciąga się od momentu zadeklarowania w dół, do końca programu.


XXXI. Porównaj zakres ważności nazw obiektów zdefiniowanych w ciele funkcji bez przydomka static i z przydomkiem static.

Taki sam - w ciele funkcji.


XXXII. Porównaj czas życia obiektów zdefiniowanych w ciele funkcji bez przydomka static i z przydomkiem static.

Wartość obiektów z przydomkiem static nie ginie po wyjściu z funkcji. Jest ona przechowywana i dostępna przy następnym wywołaniu funkcji. Jest definiowana tylko raz.
Wartość obiektów bez przydomka static ginie, przy każdym wykonaniu funkcji jest on definiowany na nowo, a po skończonej pracy usuwany.


XXXIII. Napisz program, w którym będzie funkcja void f();
Funkcja main ma wywoływać tę funkcję 100 razy. Funkcja f ma widzieć ile razy została wywołana i – przy co dwunastym wywołaniu – wypisywać na ekranie stosowny teskt(np. "nowy tuzin")

 

#include using namespace std;
void f()
{ 
static int licznik;
cout << "Jestem wywolana " << licznik << " raz!" << "\n";
if(!(licznik % 12)) cout << "Tuzin!\n"; licznik++;
}
int main()
{ 
for(int i = 0; i <= 100; i++) 
f();
}

 


XXXIV. Czy poniższą funkcję uda się skompilować poprawnie?


int sumuj(int ile)
{
int sum;
for(int i = 0; i < ile ; i++)
{
sum += 1;
}
return sum;
}
Jeśli wywołamy ją tak: sumuj (4) - to czy można powiedzieć jaka będzie wartość zwracana przez nią?

Uda się skompilować, ale nie daliśmy zmiennej sum żadnej wartości, czyli przyjmie "śmieci" i nie wiadomo jaka będzie zwracana wartość(śmieci + 4)


XXXV. Mamy nastepujące obiekty: globalny, lokalny, automatyczny, statyczny. O których z nich można powiedzieć, że wstępnie inicjalizowane zerami; o których, że zawierają śmieci; a o których nic takiego nie można powiedzieć?


Globalny - inicjalizowany 0
Lokalny automatyczny - śmieci
Lokalny statyczny - śmieci
Statyczny - inicjalizowany 0


XXXVI. Używając dostępnego Ci kompilatora napisz, skompiluj i uruchom program, który będzie się składał z dwóch plików źródłowych *.cpp. W każdym z nich mają być po dwie funkcje - (main to też funkcja). Mają się tak wywoływać, by każda z nich pracowała choć raz. W każdym pliku mają być po trzy zmienne globalne typów int, double, char, (w sumie zatem będzie ich sześć).
Niech każda z funkcji tego programu:
- najpierw wypisze na ekranie wartość każdej z sześciu zmiennych globalnych,
- zmieni wartość ich wszystkich,
- ponownie wypisze na ekranie wartość każdej z sześciu zmiennych globalnych.
Posłuż się plikiem nagłówkowym *.h, w którym wystąpią potrzebne deklaracje.


header.h

extern int liczba1, liczba2;
extern double liczba3, liczba4;
extern char znak1, znak2;
void funkcja1();
void funkcja2();
void funkcja3();

jedynka.cpp

#include <iostream> 
#include "header.h"
using namespace std;
int liczba1;
char znak1;
double liczba3;
int main()
{ 
funkcja1(); 
}
void funkcja1()
{ 
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2;
liczba1 = 20;
liczba2 = 40; 
liczba3 = 0.2; 
liczba4 = 0.4; 
znak1 = 'K';
znak2 = 'o'; 
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2 << endl;
funkcja2(); 

return;
}

dwojka.cpp

#include <iostream> 
#include "header.h"
using namespace std;
int liczba2;
char znak2;
double liczba4
;void funkcja2()
{ 
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2;
liczba3 += (liczba1 + liczba2); 
liczba4 *= liczba3; 
liczba1 += 10; liczba2 *= 30; 
znak1 = 'n'; 
znak2 = 'r'; 
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2 << endl;
funkcja3(); 
return;
}
void funkcja3()
{ 
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2;
liczba3 += (liczba1 + liczba2);
liczba4 *= liczba3;
liczba1 += 10; 
liczba2 *= 30; 
znak1 = 'a'; 
znak2 = 'd'; 
cout << "\nLiczba1 = " << liczba1 << "\nLiczba2 = " << liczba2 << "\nLiczba3 = " << liczba3 << "\nLiczba4 = " << liczba4 << "\nZnak1 = " << znak1 << "\nZnak2 = " << znak2 << endl;
return;
}

 


XXXVII. Mamy plik nagłówkowy z deklaracjami. Plik ten włączany jest dyrektywą #include w trakcie kompilacji kilku plików *.cpp naszego programu(jak w poprzednim zadaniu). Czy można w tym pliku nagłówkowym umieścić instrukcję:
extern int zmienna = 12;
Jaki odniesie to skutek? (Co na to kompilator? Co na to linker)

Nie można, kompilator zapewne potraktuje to jako zwykłą zmienną bez przydomka(zdefiniuje), a linker nic z nią nie zrobi.

 

 

 

G8loSX2.png

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...